Python类变量名与__name__的区别

9

我正在尝试理解Python类对象被赋值的变量与该类对象的__name__属性之间的关系。例如:

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

看起来我已经改变了类的__name__属性,但我不能用那个名字来引用它。我知道这有点笼统,但有人能解释一下FooFoo.__name__之间的关系吗?


4
虽然这并不直接回答你的问题,我建议阅读Ned Batchelder的《Python名称和值的真相与谣言》(http://nedbatchelder.com/text/names.html)。我认为在阅读后,你会能够自己回答你的问题。 - Steven Rumbalski
谢谢大家,提供了非常有用的信息。 - ACV
4个回答

10

很简单。根本没有关系。

当你创建一个类时,会创建一个名为你使用的名称的局部变量,指向这个类,以便你可以使用它。

该类还获得一个属性__name__,其中包含该变量的名称,因为在某些情况下这很方便,比如在pickle时。

您可以将局部变量设置为其他内容,或更改__name__变量,但这样做可能导致像pickle这样的事情无法正常工作,因此请勿这样做。


有合理的理由更改 __name__,例如当您创建类装饰器时。 - nneonneo
1
如果在装饰器中返回了一个完全不同的类,那么是的。但是您也可以使用 type() 调用构造该类,并设置 __name__。这就是我见过的做法。 - Lennart Regebro

4
__name__仅仅是自我识别,用来确定它所属实例的类型。另外一件事是它可被访问的方式,如果你重新分配它,这种方式可能会有所不同。它们两个都是在定义类时被赋值的。函数也是一样的:如果你用def声明它们,它们就会被赋给相应的名称,并获得相应的__name__属性。但是,如果你有一个lambda函数,它会获得一个__name__属性为<lambda>,因为它不知道它被分配的名称是什么。

2

简版

class Foo(object): pass创建了一个类并将其分配给本地名称Foo

Foo.__name__ = 'Bar'将一个新值分配给属性__name__。不会影响封闭作用域。

长版

类语句创建一个类并将其分配给本地范围中提供的名称。在创建类时,Python通过将其分配给类的__name__属性来告诉类它被创建的名称。

向类的属性赋值不会引入名称到本地作用域中。因此,对属性(如__name__)的任何更改都不会影响封闭作用域。


0

你需要记住,在Python中,类就像任何其他对象一样。一个对象包含一个与指向该对象的变量相关联的属性是没有意义的,因为可能有任意数量的变量名引用它。每次写入赋值语句(Bar = Foo)或将对象传递给函数时,都会创建一个新的引用。自然地,所有对象必须独立于它们被引用的方式。

__name__只是附加到类对象的信息片段,它恰好与最初分配给它的变量名相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接