关于python:“内部”列表的Pythonic访问器/ mutators

Pythonic accessors / mutators for “internal” lists

我知道属性getter和setter被认为是"unpythonic",而pythonic的方法就是简单地使用一个普通的属性,如果以后需要在访问或设置属性时触发一些功能,就使用属性decorator。

例如,使用getter和setter的Python式方法是什么?

但是,例如,当一个属性的值是一个列表时,这是如何应用的呢?

1
2
3
4
5
6
7
8
9
10
class AnimalShelter(object):
    def __init__(self):
        dogs = []
        cats = []

class Cat(object):
    pass

class Dog(object):
    pass

假设最初,接口的工作方式如下:

1
2
3
4
5
6
# Create a new animal shelter
woodgreen = AnimalShelter()

# Add some animals to the shelter
dog1 = Dog()
woodgreen.dogs.append(dog1)

这似乎符合"pythonic"的想法,即只使用简单的属性,而不创建getter、setter、mutator等。我可以创建一个addDog方法。但是,尽管不是严格地说setter(因为它改变了属性的值而不是设置属性),与我上面的解决方案相比,它仍然像setter。

但之后,假设你需要在添加狗时触发一些功能。您不能依赖于使用属性修饰器,因为添加一个dog并不是在对象上设置属性,而是检索一个该属性值的列表,并改变该列表。

对付这种情况的"Python式"方法是什么?


不费吹灰之力的是无用的getter和setter,因为python对计算属性有很强的支持。这并不意味着您不应该正确地封装您的实现。

在上面的示例中,您的AnimalShelter类处理它的"拥有"动物的方式是一个实现细节,不应公开,因此使用protected属性并公开一组相关的公共方法/属性完全是一种方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
class AnimalShelter(object):
    def __init__(self):
        self._dogs = []
        self._cats = []

    def add_dog(self, dog):
        if dog not in self._dogs:    
            self._dogs.append(dog)

    def get_dogs(self):
        return self._dogs[:] # return a shallow copy

    # etc