2010-08-03 68 views
0

请参阅下面的示例。对类实例'object'使用__class__前缀给出了预期的结果。为什么类变量在类实例'c()'中没有__class__前缀,甚至可用?在什么情况下使用?为什么在没有__class__前缀的情况下可以访问类变量?

>>> class c: 
     x=0 


>>> c.x 
0 
>>> c().x 
0 
>>> c().__class__.x 
0 
>>> c.x += 1 
>>> c.x 
1 
>>> c().x += 1 
>>> c.x 
1 
>>> c().__class__.x += 1 
>>> c.x 
2 
>>> 

回答

2

为什么是类变量,甚至 可在类实例 'C()' 没有前缀?

你可以将它有用地认为是“继承自”他们的类的实例。 IOW,当在实例x(例如x.atr)上查找名为'atr'的属性时,除非在实例本身中发现它,否则它将在该类中查找(这反过来可能导致在类的基础中查找,在mro链中查找) 。

在什么情况下使用?

最常见的一个案例:

class sic(object): 
    def foo(self): ... 

x = sic() 
x.foo() 

你可能不会想到的foo为“类变量”,但这是因为“变量”实在是毫无意义的在Python,这相当与交易名称属性。在给定的词法范围内没有用于可调用对象和不可调用对象的独立名称空间:它们都共享相同的名称空间。

因此,举例来说,如果你没有x.foo = 23,那么你可以不叫x.foo()更多 - 因为x.foo查找会给你的价值23,这是一个int,而不是调用。

另一种方式来看待这个是

class one(object): 
    foo = lambda self: ... 

class two(object): 
    def foo(self): ... 

class three(object): 
    foo = 23 

目前没有深厚的区别 - 他们一路来设置类属性foo(其中一个是不可调用的,有两个;一个与def约束声明,其中两项与作业有关;在这些类的实例的属性查找方面,存在差别而不是)。

的不可赎回属性的典型用途是:

class zap(zop): 
    zep = None 

    def blub(self): 
    if self.zep is None: self.zep = 23 
    ...&c... 

没有必要给zap一个__init__self.zep = None,并组团到超类的__init__(如果有的话) - 简单到只是继承zop“ (如果有的话)并尽可能使用class属性(当且仅当在该实例上调用blub时,它才会变成实例属性) - 对于blub永远不会存在的实例,也可以节省一点内存所谓;-)。

+0

感谢您的详细回复。你能解释一下PL在这个例子中的差异,为什么是类变量,实例变量同样在这种情况下: >>> C类: \t X = [1] \t >>> CX [1] >>> C()x.append(2) >>> CX [1,2] >>> 编辑:该代码不显示格式化的,但这个想法是使用一个列表,而不是整数的 – user284094 2010-08-03 03:30:32

+0

@ tx10:最好为此提出一个新问题。如您所见,无论是问题还是答案,都很难在评论中正确显示代码。 – 2010-08-03 04:30:58

+0

@ tx10,与@Mark达成100%的协议。无论如何,绑定一个裸号(例如通过赋值或者“def”)并且调用一个变异方法(例如你的例子中的append)完全,完全,完全和本质上是不同的,独特的,独立的和不相交的问题,很难看出为什么有人会希望他们有相同的行为(尽管显然很多Python初学者都这么做)。 – 2010-08-03 04:37:20

相关问题