gpt4 book ai didi

python-3.x - Python list 上的Python属性设定器

转载 作者:行者123 更新时间:2023-12-04 12:44:47 41 4
gpt4 key购买 nike

我正在尝试利用Python @property修改List类型的class属性。在线上的大多数示例都假定@property装饰的属性是一个奇异值,而不是可以由setter扩展的列表。

为了澄清一点问题:我不只是想给属性s赋值(一个int列表的值),而是需要对其进行修改(将一个新的int附加到当前列表中)。

我的目的是期望具有:

c = C()
c.s # [1,2,3] is the default value when instance c initiated.
c.s(5)

c.s # [1,2,3,5]

给定 C的实现,如下所示:
class C:
def __init__(self):
self._s = [1,2,3]
@property
def s(self):
return self._s
@s.setter
def s(self, val):
self._s.append(val)

现在,如果我执行 c.s(5),我会得到
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-99-767d6971e8f3> in <module>()
----> 1 c.s(5)

TypeError: 'list' object is not callable


我已经阅读了最相关的帖子:
Python property on a list

Python decorating property setter with list

但都不适合我的情况: __setitem__可以修改列表的元素,但我想扩展列表。

我当前的任务不接受使用全局属性。

在这方面,最好的解决方案是什么? (或者我从一开始就不希望在可变数据结构上使用@property吗?)谢谢!

------编辑-----

@Samuel Dion-Girardeau建议

subclass list and define its call magic method



,但我不确定我是否了解解决方案。我应该做这样的事情:
class C(list):
# somewhere when implementing class C
def __call__(self):
# even not sure what i need to do here

最佳答案

试图在这里总结和举例说明我的评论。希望这可以帮助:

解决方案1:使用常规属性,然后直接使用.append()
setter的目的不是扩展属性的值,而是替换它。在这方面,列表与int或字符串没有什么不同。在您的情况下,由于该值是可变列表,因此您可以直接在其上直接调用.append()方法。

class C():
def __init__(self):
self.s = [1, 2, 3]


>>> c = C()
>>> c.s
[1, 2, 3]
>>> c.s.append(1)
>>> c.s
[1, 2, 3, 1]
>>> c.s = [0, 0]
>>> c.s
[0, 0]

解决方案2:直接使用属性和 .append()
如果在获取/设置 s时无需检查任何内容,则上述解决方案有效。但是,如果出于某些原因需要使用属性(例如,您需要进行一些计算或检查,并希望阻止用户将其所需的任何内容设置为 s),则可以使用属性。

在这种情况下,我将防止列表中出现负数作为验证的示例。
class C():
def __init__(self):
self._s = [1, 2, 3]
@property
def s(self):
return self._s
@s.setter
def s(self, val):
if any(x < 0 for x in val):
raise ValueError('No negative numbers here!')
self._s = val

>>> c = C()
>>> c.s
[1, 2, 3]
>>> c.s.append(1)
>>> c.s
[1, 2, 3, 1]
>>> c.s = [0, 0]
>>> c.s
[0, 0]
>>> c.s = [0, -1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in s
ValueError: No negative numbers here!

请注意在这里引发错误:不是如果我调用 c.s(...)(您的问题假定是调用设置方法),而是当我使用 c.s分配给 c.s = ...时。

还要注意,此类的用户将通过 setter 间接修改 _s

解决方案3:子类 list允许该属性可调用

我绝对不建议这样做,因为它违反了此类用户的所有期望,而我只是将其作为琐事提供,并且因为它允许您最初要求的行为。
class CallableList(list):
# This is the method that actually gets called when you `c.s(...)`!
def __call__(self, *args):
self.append(*args)

class C():
def __init__(self):
self._s = CallableList([1,2,3])
@property
def s(self):
return self._s
@s.setter
def s(self, val):
self._s = CallableList(val)

>>> c = C()
>>> c.s
[1, 2, 3]
>>> c.s(1)
>>> c.s
[1, 2, 3, 1]
>>> c.s = [0, 0]
>>> c.s
[0, 0]
>>> c.s(1337)
>>> c.s
[0, 0, 1337]

请不要这样做,如果您确定它不可追溯到我,:)

关于python-3.x - Python list 上的Python属性设定器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54509105/

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