我试图用参数制作两个装饰器。 First
使用元素list
创建一个x
并调用func
。 second
只是通过传递字典中的参数来调用first
。
def first(x=1):
def wrapped(func):
l = [x]
func(l)
print(l)
return wrapped
def second(d={'x':10}):
return first(x=d['x'])
third
函数仅修改传入的列表。
我想通过简单地调用third()
使下面的四个装饰器中的任何一个成为可能。我应该如何修改我的代码?
##@second
##@second({'x':100})
##@first
##@first(x=10)
def third(l):
l.append(-1)
third()
例如:
## With @first,
## I am expecting to get [1, -1].
## With @first(x=10),
## I am expecting to get [10, -1].
## With @second,
## I am expecting to get [10, -1].
## With @second({x:100}),
## I am expecting to get [100, -1].
上面的代码是我的问题的抽象。我真正的问题是我需要一个装饰器来为我处理打开和关闭连接,所以我只需要编写代码来处理连接。
连接需要参数first
。我希望以不同的方式传递参数,即second
。 third
是我要处理的连接。我希望像普通函数一样调用third
,并且它还使用装饰器处理打开和关闭连接。抱歉,如果不能以这种方式使用装饰器,但是我真的想练习使用它。
---更新---
我想要实现的基本上是以下内容:
def context_manager(username='user', password='password'):
conn = OpenConnection()
func(conn)
CloseConnection()
def context_manager2(d={'username': 'user', 'password': 'password'}):
content_manager(username=d['username'], password=d['password'])
# @context_manager
# @context_manager('username', '123456')
# @context_manager2
# @context_manager2(d={'username': 'username', 'password': '123456'})
def execute(conn):
pass
我想使这四个装饰器中的任何一个都成为可能,并且仍然能够以execute
之类的方式调用execute()
答案 0 :(得分:3)
看起来您可能只需要了解装饰器是什么。装饰器是一个接受函数作为其唯一参数的函数,并在其位置返回一个函数。它们通常采用以下形式:
def decorator(f):
def wrapped(*args, **kwargs):
# it's important to accept any arguments to wrapped, thus *args and **kwargs
# because then you can wrap _any_ function and simply pass its arguments on.
print("Inside the wrapped function")
retval = f(*args, **kwargs) # pass the arguments through to the decorated function
print("Exiting the wrapped function")
return retval
return wrapped
这使您可以执行以下操作:
@decorator
def my_increment(x):
print("Calculating...")
return x + 1
# actually equivalent to
def my_increment(x):
print("Calculating...")
return x + 1
my_increment = decorator(my_increment)
,并预期结果如下:
>>> print(my_increment(3))
Inside the wrapped function
Calculating...
Exiting the wrapped function
4
值得注意的是:my_increment
在运行时成为修饰的函数,在调用时不是。没有装饰器功能就无法调用my_increment
。
您尝试执行的操作看起来与使用装饰器的外观不同。这对我来说就像函数链。
def first(x=1):
return [x]
def second(d=None):
if d is None:
d = {'x':10} # why do this? https://stackoverflow.com/q/1132941/3058609
return first(d['x'])
def third(lst):
return lst + [-1]
并这样称呼它:
# With @first,
# I am expecting to get [1, -1].
third(first()) # [1, -1]
# With @first(x=10),
# I am expecting to get [10, -1].
third(first(10)) # [10, -1]
# With @second,
# I am expecting to get [10, -1].
third(second()) # [10, -1]
# With @second({x:100}),
# I am expecting to get [100, -1].
third(second({'x':100})) # [100, -1]
还请注意,装饰器可以接受参数,但是您正在谈论的是(忍受...)一个接受参数的函数,该参数返回一个函数并返回一个函数。您只是抽象了一层。想象一下:
def decorator_abstracted(msg):
"""Takes a message and returns a decorator"""
# the below is almost the exact same code as my first example
def decorator(f):
def wrapped(*args, **kwargs):
print(msg)
retval = f(*args, **kwargs)
print("exiting " + msg)
return retval
return wrapped
return decorator
现在您的代码可能是
@decorator_abstracted("a decorator around my_increment")
def my_increment(x):
print('Calculating...')
return x + 1