gpt4 book ai didi

python - 在函数上定义@property

转载 作者:太空宇宙 更新时间:2023-11-04 08:34:10 25 4
gpt4 key购买 nike

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

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

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

myFn.property
// property accessed

Python 中的函数 是否有类似的东西?我知道我们不能使用 property因为它不是新式类,所以用 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

最佳答案

不可能完全按照您的意愿行事。 The descriptor protocol权力the property built-in仅在以下情况下调用:

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

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

最接近您尝试的方法是定义一个可调用的(定义__call__),它也定义了您感兴趣的描述符.创建该类的单个实例(此时您可以丢弃该类本身),它的行为将如您所愿。使 __call__ 成为 staticmethod,您将避免更改启动签名。

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

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

不,这不是您要求的(您似乎打算让一个简单的函数为您执行此操作),但您要求的是 Python 中不存在的非常特定于 JavaScript 的东西。

关于python - 在函数上定义@property,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50477609/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com