2016-04-20 44 views
4

在Python(2,3),我們可以將屬性功能:設置屬性之後類的創建提出了「‘instancemethod’對象有沒有屬性」,但attribiute顯然是有

>>> class A(object): 
...  def foo(self): 
...   """ This is obviously just an example """ 
...   return "FOO{}!!".format(self.foo.bar) 
...  foo.bar = 123 
... 
>>> a = A() 
>>> a.foo() 
'FOO123!!' 

而這涼。

但爲什麼我們不能在以後更改foo.bar?例如,在構造函數中,像這樣:

>>> class A(object): 
...  def __init__(self, *args, **kwargs): 
...   super(A, self).__init__(*args, **kwargs) 
...   print(self.foo.bar) 
...   self.foo.bar = 456 # KABOOM! 
...  def foo(self): 
...   """ This is obviously just an example """ 
...   return "FOO{}!!".format(self.foo.bar) 
...  foo.bar = 123 
... 
>>> a = A() 
123 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in __init__ 
AttributeError: 'instancemethod' object has no attribute 'bar' 

的Python聲稱沒有bar即使它打印了罰款只是前行。

>>> A.foo.bar 
123 
>>> A.foo.bar = 345 # KABOOM! 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'instancemethod' object has no attribute 'bar' 

這裏發生了什麼,也就是爲什麼我們看到的這種行爲:如果我們試圖直接改變它的類發生

同樣的錯誤?

有沒有辦法在類創建後在函數上設置屬性?

(我知道的多方案,但我明確知道關於方法的屬性在這裏,也可能是更廣泛的問題。)


動機:Django的利用來設置屬性的可能性上的方法,如:

class MyModelAdmin(ModelAdmin): 
    ... 

    def custom_admin_column(self, obj): 
     return obj.something() 
    custom_admin_column.admin_order_field ='relation__field__span' 
    custom_admin_column.allow_tags = True 
+0

'self.foo'不是您定義的'foo'函數。除了其他特色之外,'self.foo'取零參數,而你寫的'foo'函數需要一個參數。 – user2357112

回答

1

設置foo.bar內部類主體工程,因爲foo是實際foo功能。但是,當你做

self.foo.bar = 456 

self.foo是不是功能。 self.foo是一個實例方法對象,在您訪問時根據需要創建。你不能有以下幾個原因設置於它的屬性:

  1. 如果這些屬性被存儲在foo功能,然後分配給a.foo.barb.foo.bar意想不到的效果,相反,所有關於屬性分配通常期望。
  2. 如果這些屬性存儲在self.foo實例方法對象中,那麼下次訪問self.foo時它們將不會顯示,因爲下次您將獲得新的實例方法對象。
  3. 如果這些屬性存儲在self.foo實例方法對象中,並且您更改了規則,那麼self.foo始終是同一個對象,那麼這會大量膨脹Python中的每個對象以存儲幾乎不需要的一堆實例方法對象。
  4. 如果這些屬性存儲在self.__dict__中,那麼沒有__dict__的對象呢?此外,您需要提出某種名稱修改規則,或在self.__dict__中存儲非字符串鍵,這兩個鍵都有自己的問題。

如果要在類定義完成後在foo函數上設置屬性,可以使用A.__dict__['foo'].bar = 456來完成。(我使用A.__dict__來繞過A.foo是函數還是一個未綁定的方法對象,這取決於您的Python版本。如果A繼承foo,則必須處理該問題或訪問該dict它繼承foo。)

相關問題