Importing the module doesn't waste anything; the module is always fully imported (into the sys.modules
mapping), so whether you use import sys
or from sys import argv
makes no odds.
The only difference between the two statements is what name is bound; import sys
binds the name sys
to the module (so sys
-> sys.modules['sys']
), while from sys import argv
binds a different name, argv
, pointing straight at the attribute contained inside of the module (so argv
-> sys.modules['sys'].argv
). The rest of the sys
module is still there, whether you use anything else from the module or not.
There is also no performance difference between the two approaches. Yes, sys.argv
has to look up two things; it has to look up sys
in your global namespace (finds the module), then look up the attribute argv
. And yes, by using from sys import argv
you can skip the attribute lookup, since you already have a direct reference to the attribute. But the import
statement still has to do that work, it looks up the same attribute when importing, and you'll only ever need to use argv
once. If you had to use argv
thousands of times in a loop, it could perhaps make a difference, but in this specific case it really does not.
Hence, the choice between one or the other should be based solely on coding style.
In a large module, I'd certainly use import sys
; code documentation matters, and using sys.argv
somewhere in a large module makes it much clearer what you are referring to than just argv
ever would.
If the only place you use argv
is in a '__main__'
block to call a main()
function, by all means use from sys import argv
if you feel happier about that:
if __name__ == '__main__':
from sys import argv
main(argv)
I'd still use import sys
there myself. All things being equal (and they are, exactly, in terms of performance and number of characters used to write it), that is just easier on the eye for me.
If you are importing something else altogether, then perhaps performance comes into play. But only if you use a specific name in a module many times over, in a critical loop for example. But then creating a local name (within a function) is going to be faster still:
import somemodule
def somefunction():
localname = somemodule.somefunctionorother
while test:
# huge, critical loop
foo = localname(bar)
Take a look at Python's package/module hierarchy/organization, and especially in historical aspect, major additions over the course of years, most importantly the latest ones. Probably, there is no sense in inventing the wheel.
I do not know how far you want to go with your language, eg
- Do you want modules bytecode to be read from zip?
- How do you separate modules/libraries for different interpreter versions?
- Do you plan to make it seemless with distros?
- Do not forget easiness of language's own distribution (think distutils / pypi - each platform/language has its own, not always good)
I guess, Java may be another interesting example. Things can be learned from Erlang's way as well (eg https://stackoverflow.com/questions/2968914/code-hot-swapping-in-erlang).
There is a whole lot of design issues (some touched above) if you plan to see your programming language mainstream one day. Fortunately, there are great examples out there.
Some directions programming language module/package/library system design should address:
- intuitive code for both writing and using the module
- module/package objects in the code
- module/package introspection capabilities
- module/package encapsulation (how to hide unnecessary details?)
- use of interfaces/header files?
- fine-graned dispatching system, which both language own distribution utils as well as system level utils can use (avoid "DLL hell")
- storage places for bytecompiled modules
- setup system, which automates compiling both "pure" modules and modules/dependencies
- canonical place of compiled code, tests, documentation, assets in your module
Best Answer
Python at run-time keeps a lot of information around about the state of the code it's executing, and exposes quite a lot of it to programmers. So, at run time, there is an actual object (an instance of a class) called a module object that is created when a module is imported. It is a genuine Python object and you can do anything with it that you can do with a Python object. It has methods and everything.
When a function definition that gets executed (which isn't the same as the function being executed - normally the definition would be executed once for the function when the module is imported) it creates a function object, which is just a special kind of object that is a wrapper around the executable code. This too is a real object, you can set variables to it, pass it as a parameter, call it's methods, etc.