2016-03-23 28 views
1

我想爲類提供默認行爲,如下所示。未綁定方法<method>必須使用<class>實例作爲第一個參數調用

import numpy as np 

class Test: 
    def __init__(self, my_method=None): 
     self.my_method = my_method or np.min 

Test().my_method([1, 2, 3]) # >>> 1 

代碼按預期工作。爲了讓所有的默認值加在一起,便於代碼維護,我想更改代碼以

import numpy as np 

class Test: 
    default_method = np.min 

    def __init__(self, my_method=None): 
     self.my_method = my_method or Test.default_method 

Test().my_method([1, 2, 3]) # >>> TypeError 

但調用my_method失敗,出現錯誤消息unbound method amin() must be called with Test instance as first argument (got list instance instead)。奇怪的是,如果我使用內置的min而不是np.min,則代碼將按預期工作,即以下方式按預期工作。

import numpy as np 

class Test: 
    default_method = min # no np. 

    def __init__(self, my_method=None): 
     self.my_method = my_method or Test.default_method 

Test().my_method([1, 2, 3]) # >>> 1 

我錯過了什麼?

+1

在Python2中,您應該使用新的樣式類聲明。這些派生自'class Test(object):'中的'object'。我完全忘記了老式課程的語義,但認爲這可能會影響你的問題。 – msw

+0

@msw,謝謝你的興奮。但是,這個問題仍然存在於新式課堂中。 –

回答

2

作爲屬性存儲在類對象中的任何函數都被Python視爲一種方法。在Python 2中,這意味着它需要第一個參數作爲類的實例(如果通過實例請求屬性,則會自動傳遞該參數)。在Python 3中,未綁定的方法不再以這種方式檢查它們的參數(所以你的代碼將按照寫入的方式工作)。

要解決該問題上的Python 2,嘗試用staticmethod包裹default_method值:

class Test(object): 
    default_method = staticmethod(np.min) 
    #... 

這可能不是即使在Python 3的一個壞主意,因爲你也可以使用self.default_method而不是明確指定類。

至於爲什麼代碼使用min而不是np.min,那是因爲它們的實現方式不同。你可以看到,從他們的type S:

>>> type(min) 
<class 'builtin_function_or_method'> 
>>> type(np.min) 
<class 'function'> 

普通函數(如np.min)作爲描述時,他們一個班(從而讓「綁定」的行爲是造成你的問題)的屬性。像min這樣的內建函數不支持描述符協議,所以問題不會出現。

+0

太好了,謝謝! –

相關問題