От Подкаст Переполнения стека № 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/
Это не сработает; декоратор вызывается во время создания класса , что задолго до создания экземпляра (, если когда-либо произойдет). Поэтому, если вашему «декоратору» нужен экземпляр, вы должны выполнить «украшение» во время создания экземпляра:
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
.
Ваша функция «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")
Декоратор выполняется, когда класс определен, поэтому вы не можете передать ему переменную экземпляра.
Вот как мы это делали в былые времена.
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
, чтобы получить преимущества "упаковки" . Сделано по старинке, без с оператором
.
Да, многословно. Однако и никакой магии здесь нет.