2014-12-27 28 views
0

我有一個庫,可以採取類功能或具有特定簽名的正常功能。一類通常是這樣的:如何在Python 3.x中檢測未綁定方法的用法?

class MyObject(object): 
    def __init__(self, request): 
     self.request = request 

    def run(self): 
     return 'OK' 

和函數的格式是這樣的:

def my_func(request): 
    retrn 'OK' 

的這種用法是:

add_runner(MyObject, attr='run') 
add_runner(my_func) 

但有時人利用這個錯誤並通過class功能到我的書架:

add_runner(MyObject.run) 

我已經在Python 2.x中檢測到這是一個未綁定的方法,並提出錯誤提醒他們他們正在使用我的API錯誤,但在Python 3.x中我找不到任何方法來真正檢測到他們做錯了。我錯過了什麼?

回答

0

我覺得這工作得很好,我只是恨我必須檢測self

def _is_unbound(fn): 
    """ 
    This consistently verifies that the callable is bound to a 
    class. 
    """ 
    spec = inspect.getargspec(fn) 
    has_self = len(spec.args) > 0 and spec.args[0] == 'self' 
    is_bound = getattr(fn, im_self, None) is not None 

    if not is_bound: 
     if PY3 and inspect.isfunction(fn) and has_self: 
      return True 
     elif inspect.ismethod(fn): 
      return True 

    return False 
0

與Python 3,無限的方法是完全等價的功能(見Get defining class of unbound method object in Python 3討論)

檢查第一參數名稱=='self'可能有問題,因爲沒有要求方法的第一個參數爲'self'。任何有效的參數名稱都可以使用(例如'我','this'等)。

我建議使用繼續使用參數檢查,以確保調用者提供了一個函數,並帶有您期望的調用簽名。

在python3有可能未綁定的方法正確傳遞給add_runner:

class AnotherObject: 
    def run(request): 
    return "OK" 

add_runner(AnotherObject.run) 
+0

是的,但我想檢測無效使用。所以如果'run'是一個實例方法(即通過'self'綁定到類的一個實例),那麼它是無效的,因爲我不想讓自己通過它 – sontek

+0

如果'run'是一個實例方法,'inspect.ismethod(objectInstance.run)'會返回'True' – levis501

相關問題