Я использую ленивое размонтирование: umount -l
(это - нижний регистр L
)
Ленивое размонтирование. Отсоедините файловую систему от иерархии файловой системы теперь и очистку все ссылки на файловую систему, как только это больше не занято. (Требует ядра 2.4.11 или позже.)
Чтобы расширить подход __ получить __
. Это можно обобщить до декоратора-декоратора.
class _MethodDecoratorAdaptor(object):
def __init__(self, decorator, func):
self.decorator = decorator
self.func = func
def __call__(self, *args, **kwargs):
return self.decorator(self.func)(*args, **kwargs)
def __get__(self, instance, owner):
return self.decorator(self.func.__get__(instance, owner))
def auto_adapt_to_methods(decorator):
"""Allows you to use the same decorator on methods and functions,
hiding the self argument from the decorator."""
def adapt(func):
return _MethodDecoratorAdaptor(decorator, func)
return adapt
Таким образом, вы можете просто заставить ваш декоратор автоматически адаптироваться к условиям, в которых он используется.
def allowed(*allowed_methods):
@auto_adapt_to_methods
def wrapper(func):
def wrapped(request):
if request not in allowed_methods:
raise ValueError("Invalid method %s" % request)
return func(request)
return wrapped
return wrapper
Обратите внимание, что функция-оболочка вызывается для всех вызовов функций, поэтому не сделайте там что-нибудь дорогое.
Использование декоратора:
class Foo(object):
@allowed('GET', 'POST')
def do(self, request):
print "Request %s on %s" % (request, self)
@allowed('GET')
def do(request):
print "Plain request %s" % request
Foo().do('GET') # Works
Foo().do('POST') # Raises
Декоратор всегда применяется к функциональному объекту - пусть декоратор напечатает
тип его аргумент, и вы сможете это подтвердить; и обычно он также должен возвращать объект функции (который уже является декоратором с правильным __ get __
! -), хотя для последнего есть исключения.
Т.е. в коде:
class X(object):
@deco
def f(self): pass
deco (f)
вызывается в теле класса, и пока вы все еще там, f
- это функция, а не экземпляр типа метода. (Метод создается и возвращается в f
s __ get __
, когда позже f
обращается как атрибут X
или его экземпляр ).
Может быть, вы лучше объясните одну игрушку, которую вы хотите использовать для своего декоратора, чтобы мы могли больше помочь ...?
Изменить : это также относится и к декораторам с аргументами, т.е.
class X(object):
@deco(23)
def f(self): pass
тогда это deco (23) (f)
, который вызывается в теле класса,
Частичное (конкретное) решение, которое я придумал, основано на обработке исключений. Я пытаюсь создать декоратор, чтобы разрешить только определенные методы HttpRequest, но заставить его работать как с функциями, которые являются представлениями, так и с методами, которые являются представлениями.
Итак, этот класс будет делать то, что я хочу:
class methods(object):
def __init__(self, *_methods):
self.methods = _methods
def __call__(self, func):
@wraps(func)
def inner(*args, **kwargs):
try:
if args[0].method in self.methods:
return func(*args, **kwargs)
except AttributeError:
if args[1].method in self.methods:
return func(*args, **kwargs)
return HttpResponseMethodNotAllowed(self.methods)
return inner
Вот два варианта использования: украшение функции:
@methods("GET")
def view_func(request, *args, **kwargs):
pass
и украшение методов класса:
class ViewContainer(object):
# ...
@methods("GET", "PUT")
def object(self, request, pk, *args, **kwargs):
# stuff that needs a reference to self...
pass
Есть ли лучшее решение, чем использование обработки исключений?
Поскольку вы уже определяете __ get __
для использования декоратора в связанном методе, вы можете передать ему флаг, указывающий, используется ли он в методе или функции.
class methods(object):
def __init__(self, *_methods, called_on_method=False):
self.methods = _methods
self.called_on_method
def __call__(self, func):
if self.called_on_method:
def inner(self, request, *args, **kwargs):
print request
return func(request, *args, **kwargs)
else:
def inner(request, *args, **kwargs):
print request
return func(request, *args, **kwargs)
return inner
def __get__(self, obj, type=None):
if obj is None:
return self
new_func = self.func.__get__(obj, type)
return self.__class__(new_func, called_on_method=True)