Я использовал его в сборках отладки, когда компилятор настаивает на том, чтобы оптимизировать далеко переменную, которую я хочу смочь видеть, когда я ступаю через код.
Надеюсь, эта статья Брюса Экеля поможет.
Upd: Согласно статье ваш код будет выглядеть так:
class no_share(object):
def __init__(self, arg1):
self.arg1 = arg1
def __call__(self, f):
"""Don't let them in if it's shared"""
# Do something with the argument passed to the decorator.
print 'Decorator arguments:', self.arg1
def wrapped_f(request, *args, **kwargs):
if kwargs.get('shared', True):
from django.http import Http404
raise Http404('not availiable for sharing')
f(request, *args, **kwargs)
return wrapped_f
будет использоваться по желанию:
@no_share('prefs')
def prefs(request, [...])
Статья Брюса Эккеля , упомянутая Li0liQ, должна помочь разобраться в этом. Декораторы с аргументами и без них ведут себя немного по-разному. Большая разница в том, что когда вы передаете аргументы, метод __call__ вызывается один раз в __init__ и должен возвращать функцию, которая будет вызываться всякий раз, когда вызывается декорированная функция. Когда нет аргументов, метод __call__ вызывается каждый раз при вызове декорированной функции.
Что это означает для вас? Способ вызова __init__ и __call__ для @no_arg_decorator
отличается от того, как они вызываются для @decorator ('with', 'args')
.
Вот два декораторы, которые могут помочь вам. Вы можете обойтись без @no_share_on (... ) декоратор, если вы всегда используете его в круглых скобках.
def sharing_check(view, attr_name, request, *args, **kwargs):
if kwargs.get(attr_name, True):
from django.http import Http404
raise Http404('not availiable for sharing')
return view(request, *args, **kwargs)
class no_share(object):
"""A decorator w/o arguments. Usage:
@no_share
def f(request):
...
"""
def __init__(self, view):
self.view = view
def __call__(self, request, *args, **kwargs):
return sharing_check(self.view, 'sharing', request, *args, **kwargs)
class no_share_on(object):
"""A decorator w/ arguments. Usage:
@no_share_on('something')
def f(request):
...
--OR--
@no_share_on()
def g(request):
...
"""
def __init__(self, attr_name='sharing'):
self.attr_name = attr_name
def __call__(self, view):
def wrapper_f(request, *args, **kwargs):
return sharing_check(view, self.attr_name, request, *args, **kwargs)
class no_share(object):
def __init__(self, foo, view):
self.foo = foo
self.view = view
Поскольку кажется, что вы где-то ошиблись, вот более полный пример, который может помочь вам понять, что вы делаете неправильно. Использование этого в качестве подключаемого модуля должно работать.
class no_share(object):
def __init__(self, view, attr_name):
self.view = view
self.attr_name = attr_name
def __call__(self, request, *args, **kwargs):
"""Don't let them in if it's shared"""
if kwargs.get(self.attr_name, True):
from django.http import Http404
raise Http404('not availiable for sharing')
return self.view(request, *args, **kwargs)
I think closure may works here.
def no_share(attr):
def _no_share(decorated):
def func(self, request, *args, **kwargs):
"""Don't let them in if it's shared"""
if kwargs.get(attr, True):
from django.http import Http404
raise Http404('not availiable for sharing')
return decorated(request, *args, **kwargs)
return func
return _no_share