2013-07-09 136 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