2013-07-09 89 views
5

我对编程非常陌生,并开始学习python。可能看起来很愚蠢的问题,所以请原谅我的无知。 考虑下面的代码片段:了解python类属性

class Test1: 
    bar = 10  
    def display(self,foo): 
     self.foo=foo 
     print "foo : ",self.foo #80 
    def display1(self): 
     print "bar: ", self.bar #10 
     print "again foo: ", self.foo #80 

if __name__ == '__main__': 
    test1 = Test1() 
    test1.display(80) 
    test1.display1() 
    print test1.bar #10 
    print test1.foo #80 

我想了解的是什么(的地方,我们已经定义了他们WRT)的范围明智的,他们是在与所有的地方都能方便操作使用foo和酒吧之间的区别彼此唯一的区别是一个是内部函数而另一个是内部类但它们都是“实例”变量。 那么哪个是好的做法?

另外,如果我稍微修改如下显示功能:

def display(self,foo): 
     self.foo=foo 
     foo = foo 
     print "self.foo : ",self.foo 
     print "foo : ",foo 

能有人请解释蟒蛇是如何看待这一点,因为在什么区别/意义这个self关键字带来两个foo之间。

+4

不,“bar”不是*实例变量。这两者是非常不同的,这就是为什么它不是关于“良好的做法”。这是关于什么适合你的情况,因为他们有不同的目的。 – phant0m

+1

另外'self.bar'的作品,因为名称'bar'首先在实例的名称空间中搜索,然后在类中搜索。 'self.bar'工作的事实并不总是*意味着'bar'是一个实例变量。 – ersran9

回答

3

bar是一个类属性。自从班Python是对象,它们也可以有属性。bar只是碰巧住在那个对象上,而不是其中的一个实例。

由于Python解析属性查找的方式,它看起来像test1有一个bar属性,但它不。

foo另一方面在致电display(80)之后住在实例test1上。这意味着Test的不同实例可以在其各自的foo属性中具有不同的值。

当然,您可以使用类变量作为某种“共享默认值”,然后您可以使用实例属性“覆盖”,但这可能会引起混淆。

第二个问题

def display(self,foo): 
    self.foo=foo 
    foo = foo 
    print "self.foo : ",self.foo 
    print "foo : ",foo 

就让我们详细的出路:self不是一个关键字,它只是约定调用的第一个参数“自我”,你也可以把它称为“这“或”那个“或”酒吧“,如果你喜欢,但我不会推荐。

Python将传递该方法被调用的对象作为第一个参数。

def display(self,foo): 

这个foo是显示实例函数的第一个参数的名称。

self.foo=foo 

此设置与实例的名称为“foo”上,您叫display()的价值,你作为第一个参数传递的属性。使用您的示例test1.display(80),self将为test1foo80,因此test1.foo将被设置为80

foo = foo 

这什么都不做。它引用第一个参数foo

接下来的两行再次引用实例变量foo和第一个参数foo

4

bar是一个类属性,而foo是一个实例属性。主要的区别是,bar将提供给所有的类实例,而foo将提供给一个实例只有当你调用该实例

>>> ins1 = Test1() 

ins1.bar工作正常显示,因为它是一个类属性,并为所有人共享实例。如果你想要初始化时创建的实例,然后将它们放在__init__方法里面的一些实例属性

>>> ins1.foo 
Traceback (most recent call last): 
    File "<ipython-input-62-9495b4da308f>", line 1, in <module> 
    ins1.foo 
AttributeError: Test1 instance has no attribute 'foo' 

>>> ins1.display(12) 
foo : 12 
>>> ins1.foo 
12 

>>> ins1.bar 
10 

但你不能直接在这里,因为它是没有定义访问FOO 。

class A(object): 
    bar = 10 
    def __init__(self, foo): 
     self.foo = foo #this gets initialized when the instance is created 
    def func(self, x): 
     self.spam = x #this will be available only when you call func() on the instance 
...   
>>> a = A(10) 
>>> a.bar 
10 
>>> a.foo 
10 
>>> a.spam 
Traceback (most recent call last): 
    File "<ipython-input-85-3b4ed07da1b4>", line 1, in <module> 
    a.spam 
AttributeError: 'A' object has no attribute 'spam' 

>>> a.func(2) 
>>> a.spam 
2 
+1

我认为* main *的区别在于类属性是“共享”的,而不是它可用于所有实例。 – phant0m

1

就个人而言,我不喜欢的定义比__init__或类变量在你上面的例子bar其他方法中的实例变量。

再一次,我个人喜欢通过看顶部看到我班的每个成员。无论是作为实例变量使用的类变量(我通常不这么做),还是在__init__中定义的实例变量,都可以通过检查第一部分很容易地知道什么是和未定义在类中的类定义。

如果您将不再需要访问一个变量作为类成员(即你只定义它存在,以避免在__init__方法写self.variable = val,那么我会避开它。如果你可能需要访问它作为一个类变量,然后做你是bar是什么在我的书确定。

这将是给你写类的我的首选方式。

class Test1: 

    def __init__(self): 
     self.foo = None 
     self.bar = 10 

    def display(self,foo): 
     self.foo=foo 
     print "foo : ",self.foo #80 

    def display1(self): 
     print "bar: ", self.bar #10 
     print "again foo: ", self.foo #80