如何在类变量中引用类方法?
例如:
我有
class UU(object):
map = {
'username': get_username
}
@classmethod
def get_username(cls):
pass
但是,get_username
无法找到。
我尝试了UU.get_username
,但这似乎不起作用。
答案 0 :(得分:3)
类实体就像函数一样执行,然后将本地命名空间转换为类属性。
正如此正常的命名顺序要求适用;您无法引用get_username()
,因为尚未定义。
此外,即使您将classmethod
定义移到map
定义之下,您仍然可以获得未绑定的get_username()
对象。
因此,您可以在创建类之后将方法添加到映射:
class UU(object):
@classmethod
def get_username(cls):
pass
UU.map = {
'username': UU.get_username
}
请注意,这意味着从那里开始UU.map['username']
使用绑定到classmethod
类的UU
。如果您已经将UU
子类化并提供了该方法的覆盖,则您不会在子类上获得该版本。
你必须跳过更多的箍才能使这个子类工作;您必须使map
成为descriptor object,以便在映射中查找值时绑定类方法,而不是在定义映射时:
class BindingMap(dict):
def __get__(self, instance, cls=None):
return {k: v.__get__(instance, cls) if hasattr(v, '__get__') else v for k, v in self.items()}
class UU(object):
@classmethod
def get_username(cls):
pass
map = BindingMap({
'username': get_username,
})
然后地图将按需生成绑定类方法,扩展到子类:
>>> class BindingMap(dict):
... def __get__(self, instance, cls=None):
... return {k: v.__get__(instance, cls) if hasattr(v, '__get__') else v for k, v in self.items()}
...
>>> class UU(object):
... @classmethod
... def get_username(cls):
... pass
... map = BindingMap({
... 'username': get_username,
... })
...
>>> UU.map
{'username': <bound method type.get_username of <class '__main__.UU'>>}
>>> UU.map['username']
<bound method type.get_username of <class '__main__.UU'>>
>>> UU.map['username']()
>>> class UU(object):
... @classmethod
... def get_username(cls):
... print('Username for class {}'.format(cls.__name__))
... map = BindingMap({
... 'username': get_username,
... })
...
>>> UU.map
{'username': <bound method type.get_username of <class '__main__.UU'>>}
>>> UU.map['username']
<bound method type.get_username of <class '__main__.UU'>>
>>> UU.map['username']()
Username for class UU
>>> class Foo(UU):
... pass
...
>>> Foo.map
{'username': <bound method type.get_username of <class '__main__.Foo'>>}
>>> Foo.map['username']
<bound method type.get_username of <class '__main__.Foo'>>
>>> Foo.map['username']()
Username for class Foo
答案 1 :(得分:1)
你的代码不起作用的原因是因为UU的方法是在类变量之后定义的 - 所以当你试图将它添加到字典中时get_username
不存在。
试试这个:
class UU(object):
@classmethod
def get_username(cls):
pass
UU.map = {
'username': UU.get_username
}
根据您对该问题的评论,您可能会发现getattr
有用。
示例:
method_name = "get_username"
method = getattr(UU, method_name)
method()
或只是
getattr(UU, "get_username")()
不需要字典!