Python,如何添加另一个decorator来过滤Python中具有属性的现有多decorator的输出?

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

我有两个现有的修饰符在python中运行,@property@safe\u 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)
@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)