13

I was reading some code that looked basically like this:

class Foo(object):
    class_name = __module__.replace('_', '-')

To me, that looked really weird (__module__, what is that?) so I went and looked at the python data-model. A quick search shows that __module__ is a property of class objects and of function objects. However, there is no __module__ available in the global namespace (as can easily be verified by just trying to look at it and observing the NameError that results ...).

I decided to chalk this up to implementation specific behavior, but as a last check, I decided to test with other implementations I have handy. It turns out that this code executes with1

  • Cpython 2.7.6
  • Cpython 3.4.0
  • jython 2.5.3
  • PyPy 2.2.1 (Python 2.7.3)

My question is whether this behavior is actually defined anywhere in the language reference. I'm not sure why I'd want to, but could I safely rely on __module__ being in the class creation namespace or did all the implementors just decide to do this the same way?

1All linux, but I doubt that matters ...

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • 1
    Can't find anything but the [Python 2.3 *What's New*](https://docs.python.org/2/whatsnew/2.3.html#build-and-c-api-changes) states *If you dynamically allocate type objects in your extension, you should be aware of a change in the rules relating to the `__module__` and `__name__` attributes. In summary, you will want to ensure the type’s dictionary contains a `'__module__'` key; making the module name the part of the type name leading up to the final period will no longer have the desired effect. For more detail, read the API reference documentation or the source.* – Martijn Pieters Jun 30 '15 at 21:36
  • Since everyone seems to support this already, it might be reasonable asking it to be standardized. – Veedrac Jul 01 '15 at 11:02
  • @Veedrac -- I actually disagree here. It's pretty weird in python for names to just show up in your (non-global) namespace. e.g. I don't expect any magical names to show up when I create a function... – mgilson Jul 01 '15 at 18:26
  • @mgilson Too late; they already do. Some are even mandated by the standard (eg. `__class__` for use in `super()`). – Veedrac Jul 01 '15 at 18:44
  • @Veedrac -- Good point on `__class__`. I had never really read into how python3.x's `super` works. It's quite interesting really ... – mgilson Jul 01 '15 at 22:28

1 Answers1

11

What the documentation does define is that classes will have a __module__ attribute. It seems the way CPython does this is that it defines a local variable __module__ at the beginning of the class block. This variable then becomes a class attribut like any other variable defined there.

I can't find any documentation saying that __module__ has to be defined in this way. In particular, I can't find any documentation explicitly saying the attribute has to be define as a local variable in the class body, instead of being assigned as a class attribute at some later stage in class creation. This answer to a different question mentions that it works this way, and shows how it appears in the bytecode. There was a Jython bug that they fixed by making it work the same as CPython.

I'm guessing this is a CPython implementation detail that was carried over to other implementations. As far as I can tell the documentation doesn't actually say __module__ has to be available inside the class body, only on the class object afterwards.

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • 2
    Exactly; that the name is created first in the class body is not guaranteed anywhere in the language 'specification'. – Martijn Pieters Jun 30 '15 at 21:43
  • This was my thinking as well. As such, I've advised the initial authors of the code to rely on the global `__file__` (and various utilites in `os`) instead -- although I suppose I could tell them to use `__name__` ... – mgilson Jun 30 '15 at 22:19