English 中文(简体)
What are the advantages and disadvantages of the require vs. import methods of loading code?
原标题:

Ruby uses require, Python uses import. They re substantially different models, and while I m more used to the require model, I can see a few places where I think I like import more. I m curious what things people find particularly easy — or more interestingly, harder than they should be — with each of these models.

In particular, if you were writing a new programming language, how would you design a code-loading mechanism? Which "pros" and "cons" would weigh most heavily on your design choice?

最佳回答

The Python import has a major feature in that it ties two things together -- how to find the import and under what namespace to include it.

This creates very explicit code:

import xml.sax

This specifies where to find the code we want to use, by the rules of the Python search path.

At the same time, all objects that we want to access live under this exact namespace, for example xml.sax.ContentHandler.

I regard this as an advantage to Ruby s require. require xml might in fact make objects inside the namespace XML or any other namespace available in the module, without this being directly evident from the require line.

If xml.sax.ContentHandler is too long, you may specify a different name when importing:

import xml.sax as X

And it is now avalable under X.ContentHandler.

This way Python requires you to explicitly build the namespace of each module. Python namespaces are thus very "physical", and I ll explain what I mean:

  • By default, only names directly defined in the module are available in its namespace: functions, classes and so.
  • To add to a module s namespace, you explicitly import the names you wish to add, placing them (by reference) "physically" in the current module.

For example, if we have the small Python package "process" with internal submodules machine and interface, and we wish to present this as one convenient namespace directly under the package name, this is and example of what we could write in the "package definition" file process/__init__.py:

from process.interface import *
from process.machine import Machine, HelperMachine

Thus we lift up what would normally be accessible as process.machine.Machine up to process.Machine. And we add all names from process.interface to process namespace, in a very explicit fashion.

The advantages of Python s import that I wrote about were simply two:

  • Clear what you include when using import
  • Explicit how you modify your own module s namespace (for the program or for others to import)
问题回答

A nice property of require is that it is actually a method defined in Kernel. Thus you can override it and implement your own packaging system for Ruby, which is what e.g. Rubygems does!

PS: I am not selling monkey patching here, but the fact that Ruby s package system can be rewritten by the user (even to work like python s system). When you write a new programming language, you cannot get everything right. Thus if your import mechanism is fully extensible (into totally all directions) from within the language, you do your future users the best service. A language that is not fully extensible from within itself is an evolutionary dead-end. I d say this is one of the things Matz got right with Ruby.

Python s import provides a very explicit kind of namespace: the namespace is the path, you don t have to look into files to know what namespace they do their definitions in, and your file is not cluttered with namespace definitions. This makes the namespace scheme of an application simple and fast to understand (just look at the source tree), and avoids simple mistakes like mistyping a namespace declaration.

A nice side effect is every file has its own private namespace, so you don t have to worry about conflicts when naming things.

Sometimes namespaces can get annoying too, having things like some.module.far.far.away.TheClass() everywhere can quickly make your code very long and boring to type. In these cases you can import ... from ... and inject bits of another namespace in the current one. If the injection causes a conflict with the module you are importing in, you can simply rename the thing you imported: from some.other.module import Bar as BarFromOtherModule.

Python is still vulnerable to problems like circular imports, but it s the application design more than the language that has to be blamed in these cases.

So python took C++ namespace and #include and largely extended on it. On the other hand I don t see in which way ruby s module and require add anything new to these, and you have the exact same horrible problems like global namespace cluttering.

Disclaimer, I am by no means a Python expert.

The biggest advantage I see to require over import is simply that you don t have to worry about understanding the mapping between namespaces and file paths. It s obvious: it s just a standard file path.

I really like the emphasis on namespacing that import has, but can t help but wonder if this particular approach isn t too inflexible. As far as I can tell, the only means of controlling a module s naming in Python is by altering the filename of the module being imported or using an as rename. Additionally, with explicit namespacing, you have a means by which you can refer to something by its fully-qualified identifier, but with implicit namespacing, you have no means to do this inside the module itself, and that can lead to potential ambiguities that are difficult to resolve without renaming.

i.e., in foo.py:

class Bar:
  def myself(self):
    return foo.Bar

This fails with:

Traceback (most recent call last):
  File "", line 1, in ?
  File "foo.py", line 3, in myself
    return foo.Bar
NameError: global name  foo  is not defined

Both implementations use a list of locations to search from, which strikes me as a critically important component, regardless of the model you choose.

What if a code-loading mechanism like require was used, but the language simply didn t have a global namespace? i.e., everything, everywhere must be namespaced, but the developer has full control over which namespace the class is defined in, and that namespace declaration occurs explicitly in the code rather than via the filename. Alternatively, defining something in the global namespace generates a warning. Is that a best-of-both-worlds approach, or is there an obvious downside to it that I m missing?





相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签