代码之家  ›  专栏  ›  技术社区  ›  Henrik Andersson user2120121

在函数上定义@property

  •  1
  • Henrik Andersson user2120121  · 技术社区  · 6 年前

    在JavaScript中,我们可以对任何对象或函数执行以下操作

    const myFn = () => {};
    Object.defineProperties(myFn, {
        property: {
            get: () => console.log('property accessed')
        }
    });
    

    这将允许 @property 类似于为属性定义getter函数的语法 property .

    myFn.property
    // property accessed
    

    有类似的东西吗 functions 用巨蟒? 我知道我们不能用 property 因为它不是一个新样式的类,并且 lambda 具有 setattr 不起作用,因为它是一个函数。

    基本上我想达到的是 my_fn.property 是在每次调用时返回另一个类的新实例。 我现在拥有的 塞塔特 这是吗

    setattr(my_fn, 'property', OtherClass())
    

    我希望设计一个像这样的API my_fn.property.some_other_function() .

    我希望使用一个函数作为 my_fn 而不是类的实例,即使我意识到它可能更容易实现。

    下面是我想要达到的目标的要点

    def my_fn():
        pass
    
    my_fn = property('property', lambda: OtherClass())
    my_fn.property
    // will be a new instance of OtherClass on each call
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   ShadowRanger    6 年前

    你不可能做到你想要的。 The descriptor protocol 这种力量 the property built-in 仅在以下情况下调用:

    1. 描述符是 定义 在一
    2. 描述符的名称是 访问 关于一个 实例 所述类别的

    问题是,在python中定义的类隐藏函数(适当地命名 function , exposed directly as types.FunctionType 或通过电话 type() 在任何在python层定义的函数上)都是一个共享的、不可变的类,因此您不能向它添加描述符(即使可以,它们也会成为 每一个 python级别的函数,而不仅仅是一个特定的函数)。

    最接近你正在尝试的是定义一个可调用的 (定义 __call__ )这也定义了您感兴趣的描述符。为该类创建一个实例(此时可以丢弃类本身),它的行为将如您所期望的那样。制作 _呼叫__ staticmethod ,您将避免将签名更改为boot。

    例如,您想要的行为可以通过以下方式实现:

    class my_fn:
        # Note: Using the name "property" for a property has issues if you define
        # other properties later in the class; this is just for illustration
        @property
        def property(self):
            return OtherClass()
        @staticmethod
        def __call__(...whatever args apply; no need for self...):
            ... function behavior goes here ...
    my_fn = my_fn()  # Replace class with instance of class that behaves like a function
    

    现在你可以调用“函数”(实际上是一个函数,使用C++语句):

    my_fn(...)
    

    或进入物业,获得全新的 OtherClass 每次:

    >>> type(my_fn.property) is type(my_fn.property)
    True
    >>> my_fn.property is my_fn.property
    False
    

    不,这不是您所要求的(您似乎准备让一个简单的函数为您这样做),但您要求的是一个非常特定于JavaScript的东西,而这在Python中并不存在。

        2
  •  2
  •   wim    6 年前

    您想要的当前不可能,因为必须在函数类型上设置属性才能正确调用。不允许MonkeyPatch函数类型:

    >>> type(my_fn).property = 'anything else'
    TypeError: can't set attributes of built-in/extension type 'function'
    

    解决方案:改用可调用类。

    注: 你想要什么 可以 如果 PEP 575 被接受。