在函数上定义@property

2024-10-01 13:40:38 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

这将通过为属性property定义一个getter函数来允许类似于@property的语法。在

^{pr2}$

Python中的functions有什么相似之处吗? 我知道我们不能使用^{},因为它不是一个新样式的类,并且使用setattr分配一个lambda将不起作用,因为它将是一个函数。在

基本上,我想要实现的是,每当my_fn.property在每次调用中返回另一个类的新实例时。 我现在的setattr是这样的

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

我希望设计一个类似于my_fn.property.some_other_function()的API。在

我更喜欢使用函数作为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

Tags: 对象实例lambda函数getobjectmyproperty
2条回答

您所需要的当前是不可能的,因为必须在要正确调用的函数类型上设置属性。并且不允许monkeypatch函数类型:

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

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

注意:如果PEP 575被接受,那么在python3.8中,您想要的可能成为可能。在

你不可能做你想做的事。^只有在以下情况下才会调用the ^{} built-in的{a1}幂函数:

  1. 描述符是在上定义的
  2. 描述符的名称是在所述类的实例上访问

问题是,在Python中定义的函数背后的类(恰当地命名为functionexposed directly as ^{}或者间接地通过调用在Python层定义的任何函数上的type())是一个共享的、不可变的类,因此不能向它添加描述符(即使可以,它们也会成为每个Python级别函数的属性,不仅仅是一个特定的功能)。在

最接近您所尝试的是定义一个可调用的(定义__call__),它还定义了您感兴趣的描述符。创建该类的一个实例(此时可以丢弃该类本身),它的行为将如您所期望的那样。将__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++语句):

^{pr2}$

或者访问属性,每次都获得一个全新的OtherClass

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

不,这并不是您所要求的(您似乎已经准备好让一个普通函数为您完成这项工作),但您所要求的是一个Python中不存在的JavaScript特定的东西。在

相关问题 更多 >