2015-03-25 2 views
1

Как вы ссылаетесь на методы класса в переменных класса?Ссылка на методы класса внутри переменных класса

Например:

У меня есть

class UU(object): 

    map = { 
    'username': get_username 
    } 

    @classmethod 
    def get_username(cls): 
    pass 

Однако get_username не может быть найден.

Я пробовал UU.get_username, но это не работает.

+0

Зачем вы хотите это сделать? – rlms

+0

'UU.get_username'" работает ", он просто ничего не делает. Что означает «карта»? Это просто позволяет вам написать что-то многословное, как 'UU.map ['username'] 'как ссылка на метод класса. (Или это было бы, если бы 'get_username' были определены еще, а это не так.) – chepner

+0

В другой функции я хочу передать определенные ключи на карту и запустить функции, соответствующие значениям. Однако эти функции могут быть неактивными. Карта может быть выведена из класса, но в значительной степени она доступна для удобочитаемости. –

ответ

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

Нет необходимости словарь!

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 и обеспечили переопределение этого метода.

Вам нужно будет перепрыгнуть через много больше обручей, чтобы сделать эту работу для подклассов; Вы должны были бы сделать mapdescriptor 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 
+0

Код unubutu, похоже, не согласен с «Более того, вы получили бы объект unbound classmethod, даже если бы вы перенесли определение карты ниже определения get_username().», Если я правильно вас понимаю. – rlms

+1

@sweeneyrod: нет, его код показывает, что вы получаете только объект classmethod, unbound. Связанный метод выглядит как '>'. –

+1

@sweeneyrod: вы запускаете объект '' TypeError: 'classmethod' не вызываемый'] (http://stackoverflow.com/q/11058686/190597), если вы попытаетесь вызвать метод unbound classmethod с помощью моего кода. Это не полезно, поэтому я удалил свой ответ. – unutbu

Смежные вопросы