我想弄清楚如何区分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