在类变量中引用类方法

时间:2015-03-25 21:25:23

标签: python

如何在类变量中引用类方法?

例如:

我有

class UU(object):

  map = {
    'username': get_username
  }

  @classmethod
  def get_username(cls):
    pass

但是,get_username无法找到。

我尝试了UU.get_username,但这似乎不起作用。

2 个答案:

答案 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")()

不需要字典!