2013-11-17 5 views
5

Как связать класс класса внутри определения класса? Не могли бы вы посоветовать мне, как вы это сделаете? Или более конкретно, как передать объект класса внутри декоратора метода класса? Вот простой пример: я пытаюсь передать второй метод, который я объявляю декоратору первого.Определение самооценки внутри класса

def decorate(w): 
    def _wrap(f): 
     def _call(*args, **kwargs): 
      return w(f(*args, **kwargs)) 
     def _call 
    return _wrap 

class A(): 

    @dec(A.w) 
    def f(): 
     return 2 

    def w(f): 
     return fr + 5 

Как и ожидалось, возбуждается исключение

NameError: name 'A' is not defined 

В результате моего исследования я узнал, что globals() не содержит A ключ в то время как я нахожусь внутри decorate или _wrap функции, но определенные внутри _call. Поэтому я мог бы, вероятно, найти переданный метод по имени строки (например, @dec('A.w')), но в этом случае невозможно кэшировать поиск метода внутри _wrap закрытия.

Итак, как вы это исправите? :)

+1

Класс еще не существует, пока он определяется. Кроме того, 'w' не существует, когда' f' определяется, потому что 'w' появляется после' f' в файле. Если вы переместите 'w' сначала, вы можете заставить его работать, используя' @dec (w) '. – BrenBarn

+1

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

ответ

4

Вы не можете, поскольку при определении класса класс еще не существует.

Вы можете применить декоратор после того, как класс был создан:

class A(): 
    def f(self): 
     return 2 

    def w(self, f): 
     return fr + 5 

A.f = dec(A.w)(A.f.__func__) 

или вы можете поменять порядок двух определений методов и относятся к w как локальное имя еще:

class A(): 
    def w(self, f): 
     return fr + 5 

    @dec(w) 
    def f(self): 
     return 2 

В обоих случаях вы передаете вызываемый A.w, то есть не, связанный с экземпляром. Нет self не будет принят, поэтому вам нужно добавить, что сами, в декоратора:

def decorate(w): 
    def _wrap(f): 
     def _call(self, *args, **kwargs): 
      return w(self, f(*args, **kwargs)) 
     def _call 
    return _wrap 

Если вы не ожидали w к быть связаны (он действует как статический метод вместо), вы можете просто используйте здесь обычную функцию.

Вообще говоря, создание декоратора для вызова другого метода в том же экземпляре несколько бессмысленно; почему бы просто не позвонить w с f, напрямую?

class A(): 
    def f(self): 
     return self.w(2) 

    def w(self, f): 
     return fr + 5