- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
菊花链式 Python/Django 自定义装饰器是一种很好的风格吗?并传递与收到的参数不同的参数?
我的许多 Django View 函数都以完全相同的代码开始:
@login_required
def myView(request, myObjectID):
try:
myObj = MyObject.objects.get(pk=myObjectID)
except:
return myErrorPage(request)
try:
requester = Profile.objects.get(user=request.user)
except:
return myErrorPage(request)
# Do Something interesting with requester and myObj here
仅供引用,这是 urls.py 文件中相应条目的样子:
url(r'^object/(?P<myObjectID>\d+)/?$', views.myView, ),
在许多不同的 View 函数中重复相同的代码根本不是 DRY。我想通过创建一个装饰器来改进它,它会为我做这些重复的工作,并使新的 View 功能更清晰,看起来像这样:
@login_required
@my_decorator
def myView(request, requester, myObj):
# Do Something interesting with requester and myObj here
所以这是我的问题:
最佳答案
这是一个非常有趣的问题! Another one has already been answered in depth on the basic usage of decorators .但它并没有提供太多关于修改参数的见解
你可以在另一个问题上找到一个堆叠装饰器的例子,下面的解释隐藏在一个非常、非常又长又详细的答案中:
Yes, that’s all, it’s that simple. @decorator is just a shortcut to:
another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)
这就是魔法。作为python documentation声明:装饰器是返回另一个函数的函数。
这意味着您可以:
from functools import wraps
def decorator1(f):
@wraps(f)
def wrapper(*args, **kwargs):
do_something()
f(*args, **kwargs)
return wrapper
def decorator2(f):
@wraps(f)
def wrapper(*args, **kwargs):
do_something_else()
f(*args, **kwargs)
return wrapper
@decorator1
@decorator2
def myfunc(n):
print "."*n
#is equivalent to
def myfunc(n):
print "."*n
myfunc = decorator1(decorator2(myfunc))
Python 装饰器可能会让那些使用一种语言学习 OOP 的开发人员感到困惑,其中 GoF 已经使用了一半的字典来命名修复语言故障的模式是事实上的设计模式购物。
GoF 的装饰器是它们正在装饰的组件(接口(interface))的子类,因此与该组件的任何其他子类共享此接口(interface)。
Python 装饰器是返回函数 ( or classes ) 的函数。
Python 装饰器是一个返回函数的函数,任何函数。
大多数装饰器都旨在扩展装饰功能而不妨碍其预期行为。它们是根据 GoF 对装饰器模式的定义而设计的,装饰器模式描述了一种在保持对象接口(interface)的同时扩展对象的方法。
但是GoF的装饰器是一种模式,而python的装饰器是一个特性。
Python 装饰器是函数,这些函数应该返回函数(当提供函数时)。
让我们采用另一个 GoF 模式:Adapter
An adapter helps two incompatible interfaces to work together. This is the real world definition for an adapter.
[An Object] adapter contains an instance of the class it wraps. In this situation, the adapter makes calls to the instance of the wrapped object.
以一个对象为例——比如一个调度员,他会调用一个函数,该函数接受一些定义的参数,并接受一个函数来完成这项工作但提供另一组参数。第二个函数的参数可以从第一个函数的参数中导出。
一个函数(它是 python 中的一等对象)将获取第一个参数并派生它们以调用第二个并返回从其结果派生的值将是一个适配器。
为传递给它的函数返回适配器的函数将是一个适配器工厂。
Python 装饰器是函数返回函数。包括适配器。
def my_adapter(f):
def wrapper(*args, **kwargs):
newargs, newkwargs = adapt(args, kwargs)
return f(*newargs, **newkwargs)
@my_adapter # This is the contract provider
def myfunc(*args, **kwargs):
return something()
我会说,该死的,又一个内置模式!但是你必须忘记 GoF 装饰器,只记住 python 装饰器是返回函数的函数。因此,您正在处理的接口(interface)是包装函数之一,而不是装饰函数。
一旦你装饰了一个函数,装饰器就定义了契约,要么告诉它保留被装饰函数的接口(interface),要么将它抽象出来。你不再调用那个装饰函数,尝试它甚至很棘手,你调用包装器。
关于python - 菊花链式 Python/Django 自定义装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22651031/
我是一名优秀的程序员,十分优秀!