Python,如何添加另一个decorator来过滤Python中具有属性的现有多decorator的输出?
我有两个现有的修饰符在python中运行,@property和@safe\u property。那些装饰器是无法更改的,它们是我无法访问的代码的一部分Python,如何添加另一个decorator来过滤Python中具有属性的现有多decorator的输出?,python,decorator,python-decorators,Python,Decorator,Python Decorators,我有两个现有的修饰符在python中运行,@property和@safe\u property。那些装饰器是无法更改的,它们是我无法访问的代码的一部分 def safe_property(original_property): def wrap(self): try: return original_property(self) except AttributeError as e: pass re
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)
@property
@safe_property
@my_decorator
def do_func(self):
print("inside do_func!")
return [2,3,4]
输出对我有好处!:
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
(,)
{}
(,对)
没有一个
如何仅从以下列表中筛选返回列表的奇数**,例如**:
做什么
谢谢您正在将装饰器应用于
@属性
装饰器的输出。那个装饰器生成的是一个函数,而不是一个函数。这是因为装饰器是从函数定义中向外应用的;看我的;因此,首先应用@safe\u属性
,然后应用@property
,然后应用@my\u decorator
如果您想修饰getter函数,请将decorator放在def
语句的正上方,它将首先执行,decorator返回的任何内容都将传递给safe\u属性()
decorator(它添加了自己的包装函数):
或者,由于@safe\u属性
也会生成一个适合作为getter函数的包装函数,您可以将修饰符放在@safe\u属性
和@property
行之间,以包装返回前者的包装函数:
@property
@my_decorator
@safe_property
def do_func(self):
print("inside do_func!")
return [2,3,4]
无论哪种方式,您的decorator包装都传递了可调用的decoration,并且应该返回一个替换。属性获取程序只接受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
decorator是如何工作的)
例如,您可以从property().fget
属性中提取getter,然后返回一个适当的替换项(这将是另一个property()
对象):
请注意,属性getter
函数将只传递给self
,不可能有其他属性getter参数
但是,直接处理
属性
对象并没有比将decorator放低一行的任何优势,它只会因为必须添加prop.fget
引用和属性(…)
返回值而使事情复杂化。问题在于如何嵌套decorator@property
应该是最顶级的decorator,如果您的其他decorator处理函数的话property()
将函数转换为其他内容(一个属性;它是一个描述符),因此它上面的任何修饰符都需要处理属性而不是函数。谢谢,我正在尝试理解您的解决方案,我正在执行您的代码,当我尝试发送print时,代码中的some_标志是什么(a.do_func(True))@raptor0102它是实例上的一个示例属性。它不存在,我只是想显示你有权访问实例本身。谢谢你,你帮助我解决了我的问题,代码现在工作正常。我感谢你的努力
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)