我想弄清楚如何區分python模塊級函數和尚未綁定到對象實例的方法。當函數是一個未綁定的實例方法時,我需要一個定義該方法的類的句柄。 inspect.ismethod()
不起作用,因爲該方法尚未綁定到對象實例。 type()
爲模塊級函數和未綁定方法返回「函數」。區分python函數和類函數
用例是一個使用方法和函數裝飾器的插件框架。我有一個通用的'模型'類,可以分類添加功能。使用@register_action(name)
裝飾器在子類中定義插件「操作」。在導入時調用裝飾器函數來註冊動作。 gui然後爲字典中的每個ACTION添加菜單項 - 但是gui應該只添加一個動作,如果gui的Model類是註冊了函數/方法的類的實例。
一些示例代碼如下。現在我的解決方案是解析fcn描述符的文本,然後檢查是否class_str == str(model.__class__).split('.')[-1].strip("'>")
。我也嘗試將SpecialModel傳遞給裝飾器,但是當裝飾器函數運行時SpecialModel沒有定義,所以不起作用。註冊類方法操作必須有更好的解決方案。
注:因爲它是不可能通過SpecialMethod
到register_action
裝飾,因爲SpecialMethod
沒有定義,我可能需要調用get_class_from_function
當談到時間來註冊與GUI的操作。
ACTIONS = dict()
### HACK -- best I could do, but want actual Class, not class_name ###
# FIXME : want to return None, Model, SpecialModel, etc.
def get_class_from_function(fcn):
qname = fcn.__qualname__.split('.')
if len(qname) > 1: # this is (likely) a class function
cls_name = qname[0]
return cls_name
else:
return None
def register_action(name):
def register_decorator(fcn):
global ACTION
cls = get_class_from_function(fcn)
ACTION[ name ] = (fcn, cls)
return fcn
return register_decorator
@register_action("Help/About")
def help_about_function(model):
pass
class Model(object):
def __init__(self):
pass
@register_action("File/Load")
def load(self):
pass
class SpecialModel(Model):
@register_action("Special/Custom Action")
def specialact(self):
pass
你有沒有考慮檢查是否第一參數是'self'(例如'args = inspect.getargspec(thing).args; args和args [0] =='self'')?這不是保證,但是一個很好的指示。 – jonrsharpe
我相信在Python 3中,自由函數和類定義中定義的函數沒有區別。事實上,你可以在模塊級定義一個函數,然後將它「粘貼」到類中,它就像它被定義爲一個方法一樣工作。也許這不是最好的方法......也許應該由班級完成註冊方法的操作。也就是說,無論何時定義一個'Model',即它的方法應該被註冊。這可以使用類裝飾器或者元類來完成。 – jme
* class method *是一門藝術術語。據我所知,你對這個術語的使用是不正確的,只是混淆了這個問題。 – 7stud