Как я могу использовать переменную экземпляра класса в качестве аргумента в пользу декоратора метода в Python?

От Подкаст Переполнения стека № 11 :

Atwood: Это. Хорошо, так, чтобы прибывает из, это - проект некоторый инженер Google, я думаю, записал его - это называют, "Украшают". И это немного интересно в этом, это на самом деле выводит всю подсветку синтаксиса, которая кажется, что это не могло возможно работать - это звучит на самом деле безумным, если Вы думаете об этом. Но это на самом деле добрый из работ. Теперь, он только поддерживает его для, существуют определенные диалекты, которые просто действительно не работают хорошо с ним, но для всех диалектов такой, Вы нашли бы на Google. Я думаю, что это прибывает из Google Code Google. Это - фактический код, это - фактический JavaScript, который находится на Google Code, который выделяет это код, который возвращается, когда Вы размещаете проекты на Google Code. И Вы и Вы, гм, потому что я думаю, что они используют Подрывную деятельность, таким образом, можно на самом деле нажать через...

Spolsky: , Как они знают, как они даже знают, в каком языке Вы пишете? И поэтому, какой комментарий и...

Atwood: я не знаю. Это является сумасшедшим. Это - prettify.js, поэтому если кто-либо заинтересовал рассмотрением этого, просто сделайте веб-поиск "prettify.js", и Вы найдете его.

И вот то, где можно найти prettify.js: http://code.google.com/p/google-code-prettify/

5
задан 5 August 2009 в 08:49
поделиться

4 ответа

Это не сработает; декоратор вызывается во время создания класса , что задолго до создания экземпляра (, если когда-либо произойдет). Поэтому, если вашему «декоратору» нужен экземпляр, вы должны выполнить «украшение» во время создания экземпляра:

def get_decorator(arg1):
    def my_decorator(function):
        print "get_decorator argument: %s" % arg1
        return function
    return my_decorator

class Foo(object):
    def __init__(self, arg1):
        self.var1 = arg1
        self.method1 = get_decorator(self.var1)(self.method1)

    def method1(self):
        print "method1"

foo = Foo("abc")
foo.method1()

Обратите внимание, что я изменил имена функций в соответствии с их значениями; фактический «декоратор», то есть функция, которая (потенциально) изменяет метод, в вашем случае является оболочкой , а не decorator1 .

9
ответ дан 18 December 2019 в 10:47
поделиться

Ваша функция «warper» на самом деле является декоратором, а не варпером. Ваша функция decorator1 является конструктором-декоратором. Если вы хотите иметь доступ к self.var1 во время выполнения, вам нужно сделать варпер, а не декоратор:

def decorator(function):
  def wrapper(self,*args,**kwargs):
    print "Doing something with self.var1==%s" % self.var1
    return function(self,*args,**kwargs)
  return wrapper

class Foo(object):
  def __init__(self, arg1):
    self.var1 = arg1

  @decorator
  def method1(self):
    print "method1"

foo = Foo("abc")
foo.method1()

Если вы хотите иметь более общий декоратор, лучше объявить вызываемый класс:

class decorator:
  def __init__(self,varname):
      self.varname = varname
  def __call__(self,function):
    varname=self.varname
    def wrapper(self,*args,**kwargs):
      print "Doing something with self.%s==%s" % (varname,getattr(self,varname))
      return function(self,*args,**kwargs)
    return wrapper

Использование:

  @decorator("var1")
5
ответ дан 18 December 2019 в 10:47
поделиться

Декоратор выполняется, когда класс определен, поэтому вы не можете передать ему переменную экземпляра.

1
ответ дан 18 December 2019 в 10:47
поделиться

Вот как мы это делали в былые времена.

class Foo(object):
    def __init__(self, arg1):
        self.var1 = arg1

    def method1(self):
        self.lock()
        try:
            self.do_method1()
        except Exception:
            pass # Might want to log this
        finally:
            self.unlock()

    def do_method1(self):
        print "method1"

    def lock(self):
        print "locking: %s" % self.arg1

    def unlock(self):
        print "unlocking: %s" % self.arg1

Теперь подклассу нужно всего лишь o переопределить do_method1 , чтобы получить преимущества "упаковки" . Сделано по старинке, без с оператором .

Да, многословно. Однако и никакой магии здесь нет.

1
ответ дан 18 December 2019 в 10:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: