Module-level functions and the module type

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Aug 17 11:59:34 EDT 2014


Chris Angelico wrote:

> In a class definition, you have explicit state parameters on your
> functions - 'self':
> 
> class C:
>     def foo(self, arg):
>         # blah blah
> 
> At module level, there's equivalent state - the function "knows" what
> module it came from - but it's implicit:
> 
> def foo(arg):
>     # blah blah
> 
> print(foo.__globals__)
> 
> How hard would it be to unify these, and make modules into classes?

There's a difference though: modules are instances of ModuleType. While it's
true that classes are instances of type, you cannot instantiate a module
instance.


> This would then allow stuff like properties, metaclasses, and so on,
> all with exactly the same semantics as they have in classes.
> 
> Obviously this would be a huge backward-compatibility break if it
> happened everywhere, but what I'm looking at here is a way to
> basically bless this kind of concept:
> 
> # spam.py
> class RealSpam:
>     # module contents here
> 
> import sys
> sys.modules[__name__] = RealSpam()

But that is already blessed! You can stick anything you like in sys.modules,
and import will accept it. This is been true for a long time:

[steve at ando ~]$ python2.4
Python 2.4.3 (#1, Jan  9 2013, 06:49:54)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
py> import sys
py> sys.modules['lunch'] = 'spam spam spam'
py> import lunch
py> lunch.upper()
'SPAM SPAM SPAM'

There is a special meaning to given to None:

py> sys.modules['breakfast'] = None
py> import breakfast
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ImportError: No module named breakfast


but otherwise you should be able to use anything you like. The tricky part
is having a module replace itself on the fly.

> So the question is: Why is state implicit in one and explicit in the
> other? Which option is really the better way to do things?

Global state is implicit so that we can write code with unqualified variable
names, and the current namespace is implicit:

# Module m.py
x = 1
y = x + 1

instead of this:

this.x = 1
this.y = this.x + 1

Also, the interpreter would need to handle "this" specially, it can't just
be a regular variable. If it was, you would need to look it up in an
explicitly stated namespace, which is an ordinary variable that needs a
namespace... 

x  # Where's the namespace for x?
this.x  # Where's the namespace for this?
this.this.x
this.this.this.x
this.this.this.this.x
...

*Somewhere* there has to be an implicit namespace. Might as well be right at
the beginning.

But inside class methods we have a problem:

class X:
    def method():
        a = b + c

We can trivially decide on a rule that a must be a local, but how about b
and c? Are they globals or attributes of the instance? Python decided on
giving globals (well, actually nonlocals) priority, and requiring an
explicit self, so we can write this:

    def method(self):
        a = self.b + len(c)

instead of this:

    def method():
        locals.a = b + globals.len(globals.c)


-- 
Steven




More information about the Python-list mailing list