Python装饰属性setter方法的列表

10
globalList = []
class MyList:
    def __init__(self):
        self._myList = [1, 2, 3]

    @property
    def myList(self):
        return self._myList + globalList
    @myList.setter
    def myList(self, val):
        self._myList = val

mL1 = MyList()
print("myList: ", mL1.myList)
mL1.myList.append(4)
print("after appending a 4, myList: ", mL1.myList)
mL1.myList.extend([5,6,"eight","IX"])
print("after extend, myList: ", mL1.myList)

结果:

myList:  [1, 2, 3]
after appending a 4, myList:  [1, 2, 3]
after extend, myList:  [1, 2, 3]

我面临的问题是mL1.myList.append(4)和mL1.myList.extend([5,6,"eight","IX"])不会修改mL1对象中的_myList属性。我该如何解决这个问题呢?


你能修正一下缩进吗?我不确定第二个函数应该缩进到哪里。 - David Robinson
我不清楚您期望的行为是什么。append() 应该添加到 _myList(这意味着值不会像预期的那样添加到末尾)还是 globalList?无论哪种方式,很明显这不起作用,因为返回的值是通过连接两个其他列表生成的新列表。扩展它不会以某种方式进行修改。 - Gareth Latty
append() 应该添加到 _myList 中,extend() 也是如此。 - drerD
此外,列表是否通过属性访问很重要吗?让 MyList 直接实现 __getitem__()append() 等方法使其本身就像一个序列会更有意义,并且也更容易实现。 - Gareth Latty
重要的是我能够通过MyList对象同时访问globalList和_myList。自己实现append()是个好主意,谢谢! - drerD
2个回答

9

我为类对象定义了名为append()和extend()的方法。它们分别向成员变量myList添加元素并将成员变量myList扩展。

global globalList  
globalList = []
class MyList():
    def __init__(self):
        self._myList = [1, 2, 3]

    @property
    def myList(self):
        return self._myList + globalList
    @myList.setter
    def myList(self, val):
        self._myList = val

    def append(self, val):
        self.myList = self.myList + [val]
        return self.myList  

    def extend(self, val):
        return self.myList.extend(val)


mL1 = MyList()
print("myList: ", mL1.myList)
mL1.append(4)
print("after appending a 4, myList: ", mL1.myList)
mL1.myList.extend([5,6,"eight","IX"])
print("after extend, myList: ", mL1.myList)

结果为:

>>> 
('myList: ', [1, 2, 3])
('after appending a 4, myList: ', [1, 2, 3, 4])
('after extend, myList: ', [1, 2, 3, 4, 5, 6, 'eight', 'IX'])

谢谢您的建议! - drerD
6
代码存在严重问题 :) MyList没有继承自object,这破坏了setter属性,因此在将值赋给myList后,它将成为一个普通的列表。修复此问题后,每次调用append()时,它都会将globalList添加到_mylist中。而extend实现也有问题,应该扩展_myList,否则它只会扩展由属性返回的临时列表。最后,例子调用了mL1.myList.extend而不是mL1.extend。 - user1346466

3

我会创建list的子类并重写一些方法:

import itertools

class ExtendedList(list):
    def __init__(self, other=None):
        self.other = other or []

    def __len__(self):
        return list.__len__(self) + len(self.other)

    def __iter__(self):
        return itertools.chain(list.__iter__(self), iter(self.other))

    def __getitem__(self, index):
        l = list.__len__(self)

        if index > l:
            return self.other[index - l]
        else:
            return list.__getitem__(self, index)

它应该与几乎所有内容兼容:

In [9]: x = ExtendedList([1, 2, 3])

In [10]: x
Out[10]: [1, 2, 3]

In [11]: x.append(9)

In [12]: x
Out[12]: [9, 1, 2, 3]

In [13]: x.extend([19, 20])

In [14]: x
Out[14]: [9, 19, 20, 1, 2, 3]

In [15]: sum(x)
Out[15]: 54

嗨,感谢您的回答,看到您如何实现它很有趣。希望您不介意我问一些简单的问题:self.other = other or [],这里使用了短路评估吗?所以如果没有提供其他参数,那么它将是一个空列表? - drerD
@user14042:是的,如果other为真值(在这种情况下不是None或空列表),它将被返回。如果不是,则返回另一侧。 - Blender

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接