9

I'm trying to understand the relationship between the variable a Python class object is assigned to and the __name__ attribute for that class object. For example:

In [1]: class Foo(object):
   ...:     pass
   ...: 

In [2]: Foo.__name__ = 'Bar'

In [3]: Foo.__name__
Out[3]: 'Bar'

In [4]: Foo
Out[4]: __main__.Bar

In [5]: Bar
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-962d3beb4fd6> in <module>()
----> 1 Bar

NameError: name 'Bar' is not defined

So it seems like I have changed the __name__ attribute of the class but I can't refer to it by that name. I know this is a bit general but could someone explain the relationship between Foo and Foo.__name__?

ACV
  • 1,895
  • 1
  • 19
  • 28
  • 4
    Although this does not answer your question directly, I suggest reading Ned Batchelders's [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html). I think you will be able to answer your own question after reading it. – Steven Rumbalski Aug 20 '13 at 04:06
  • Thanks everyone, very helpful information. – ACV Aug 20 '13 at 22:09

4 Answers4

10

It's simple. There is no relationship at all.

When you create a class a local variable is created with name you used, pointing at the class so you can use it.

The class also gets an attribute __name__ that contains the name of that variable, because that's handy in certain cases, like pickling.

You can set the local variable to something else, or change the __name__ variable, but then things like pickling won't work, so don't do that.

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • There are valid reasons for changing `__name__`, though, e.g. when you are creating a class decorator. – nneonneo Aug 20 '13 at 04:05
  • 1
    Well, if you are returning a completely different class in that decorator, yes. But then you can also construct that class with a `type()` call, which sets `__name__`. This is how I've seen it done. – Lennart Regebro Aug 20 '13 at 04:41
4

__name__ is mere self-identification, in oder to know what type an instance of it really is.

The other thing is the way it can be accessed with. That can vary if you re-assign it.

They both are assigned at the time you define the class.

It works the same way with functions: if you def them, they get assigned to the given name and they get the respective __name__ attribute.

OTOH, if you have a lambda function, it gets a __name__ attribute of <lambda>, because it doesn't know the name it gets assigned to.

glglgl
  • 89,107
  • 13
  • 149
  • 217
2

Short version

class Foo(object): pass creates a class and assigns it to local name Foo.

Foo.__name__ = 'Bar' assigns a new value to attribute __name__. The enclosing scope is not affected.

Long version

The class statement creates a class and assigns to the name provided in the local scope. When creating a class Python tells the class the name it was created with by assigning it to the class's __name__ attribute.

Assigning to a class's attribute does not introduce a name into the local scope. Therefore any changes to attributes (such as __name__) do not affect the enclosing scope.

Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
0

You need to keep in mind that in python a class is just an object like any other. It wouldn't make sense for an object to contain an attribute that was linked to a variable that refers to the object, because there could be any number of variable names referring to it. Any time you write an assignment (Bar = Foo) or pass the object to a function, you have a new reference. Naturally all objects must be independent of how they are referenced.

__name__ is simply a piece of information attached to the class object, which happens to be the same as the variable name it's initially assigned to.

nmclean
  • 7,564
  • 2
  • 28
  • 37