类体像函数一样被执行,然后本地命名空间变成类属性。
因此适用正常的命名顺序要求;您不能引用get_username(),因为它尚未定义。
此外,即使您将map 定义移到get_username() 定义下方,您也会得到未绑定的classmethod 对象。
因此,您需要在创建类之后将该方法添加到映射中:
class UU(object):
@classmethod
def get_username(cls):
pass
UU.map = {
'username': UU.get_username
}
请注意,这意味着从那里开始UU.map['username'] 正在使用绑定到UU 类的classmethod。如果您曾经对 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