python - Python,如何添加另一个装饰器来过滤现有多装饰器的输出与python中的属性?
问题描述
我有 2 个现有的装饰器可以在 python 中运行,@ property和@safe_property。这些装饰器无法更改,它们是我无权访问的代码的一部分。
def safe_property(original_property):
def wrap(self):
try:
return original_property(self)
except AttributeError as e:
pass
return wrap
class MyClass(object):
def __init__(self):
pass
@property
@safe_property
def do_func(self):
print("inside do_func!")
return [2,3,4]
通过调用函数:
a = MyClass()
print(a.do_func)
输出对我有好处!:
inside do_func!
[2, 3, 4]
现在,另一个特性来了,我试图根据(可选)附加参数过滤掉do_func的一些返回值。这意味着一些用户可以像往常一样继续工作并调用:
print(a.do_func)
而其他人可以使用过滤器调用:
print(a.do_func(True))
为了尝试这个,我创建了另一个名为my_decorator的装饰器,例如:
def my_decorator(*args, **kwargs):
print(args)
print(kwargs)
def wrapper(*args):
print(args)
if args[1] == True:
return
# how do I return filter?
else:
return #without the filter?
return wrapper
class MyClass(object):
def __init__(self):
pass
@my_decorator
@property
@safe_property
def do_func(self):
print("inside do_func!")
return [2,3,4]
此功能的当前输出是:
(<property object at 0x02AF0090>,)
{}
(<__main__.MyClass object at 0x00BCDBB0>, True)
None
我怎样才能只过滤奇数**例如,**来自: do_func的返回列表?
谢谢
解决方案
您正在将装饰器应用于装饰器的输出@property
。该装饰器产生一个property()
对象,而不是一个函数。这是因为装饰器是从函数定义向外应用的;请参阅我对装饰器执行顺序的回答;so@safe_property
首先应用,然后是@property
,然后是@my_decorator
。
如果你想装饰 getter 函数,请将你的装饰器放在def
语句的正上方,它将首先执行,无论你的装饰器返回什么都将传递给safe_property()
装饰器(它添加了自己的包装函数):
@property
@safe_property
@my_decorator
def do_func(self):
print("inside do_func!")
return [2,3,4]
或者,看到 as@safe_property
也会产生一个适合作为 getter 函数的包装器函数,您可以将装饰器放在@safe_property
和@property
行之间以包装返回前者的包装器函数:
@property
@my_decorator
@safe_property
def do_func(self):
print("inside do_func!")
return [2,3,4]
无论哪种方式,您的装饰器包装器都会传递可调用来装饰,并且应该返回一个替换。属性 getter 仅 take self
,您的替换也将被调用self
,并且没有其他参数:
def my_decorator(func):
def wrapper(self): # a replacement getter function, so only self is passed in
result = func(self) # call the original getter
if self.some_flag: # you can access the instance in the wrapper
# return only odd values from the getter
return [i for i in result if i % 2]
else:
# otherwise return the values unchanged
return result
return wrapper
放在@my_decorator
顶部是装饰一个property()
对象,而不是一个函数,所以你需要专门处理传递这样一个对象(你可以在我之前写的答案@property
中看到装饰器是如何工作的)。
例如,您可以从属性中提取property().fget
getter ,然后返回适当的替换(这将是另一个property()
对象):
def my_decorator(prop):
getter = prop.fget
def wrapper(self): # a replacement getter function, so only self is passed in
result = getter(self) # call the original getter, taken from the property
if self.some_flag: # you can access the instance in the wrapper
# return only odd values from the getter
return [i for i in result if i % 2]
else:
# otherwise return the values unchanged
return result
# return a new property object, with the wrapper as the getter function
# and copying across all other property attributes
return property(wrapper, prop.fset, prop.fdel, prop.doc)
请注意,属性getter
函数只会被传递self
,没有其他可能的属性获取器参数。
然而,property
直接处理一个对象并没有比将装饰器放低一行有任何优势,它只会使事情复杂化,因为必须添加prop.fget
引用和property(...)
返回值。
推荐阅读
- reactjs - Firebase:名为“[DEFAULT]”的 Firebase 应用程序已存在(应用程序/重复应用程序)。Nextjs + 火力基地
- r - 使用表情符号时在 `github_document` 中创建的不必要列表
- javascript - 如何为具有存储过程的表创建增量记录 ID?
- python - 正确的示例输出但未在 codechef 上被接受
- laravel - Vue js 如何在菜单外单击时关闭引导下拉菜单
- c# - 添加到实体中的集合
- julia - 微分方程求解()不起作用(朱莉娅)
- javascript - 不会在 eval 语句中评估代码的节点 cli 标志
- javascript - 为什么购物车 React-Redux 不更新?
- matlab - 如何证明二维 DFT 的信号可分离性?MATLAB