Class 对象不适当地共享属性

Class Objects Inappropriately Sharing Attribute

我有一个带有属性的 class。最初它包含一条错误消息的单个字符串。我想我会变得聪明并将它变成一个列表,所以每次我 'set' 属性时,它不会替换字符串,而是将字符串附加到列表中。

但是,现在 err 属性在对象之间共享,而不是每个对象都是唯一的。

这是我的代码(test.py,在这个例子中被删减到最小值)

#!/usr/bin/python3
# pylint: disable=C0301

'''Testing MyHost class'''

class MyHostGood:           # pylint: disable=R0903
    '''Host class'''
    err = ''
    name = ''

    def __init__(self, name=''):
        '''Constructor'''
        self.name = name

    def __str__(self):
        '''Return a printable user representation of the object - print(x)'''
        info = f'{self.name}:'
        # These are error/warning messages
        if self.err:
            info += f'\n└ ERROR: {self.err}'
        return info

class MyHostBad:           # pylint: disable=R0903
    '''Host class'''
    _err = []
    name = ''

    def __init__(self, name=''):
        '''Constructor'''
        self.name = name

    def __str__(self):
        '''Return a printable user representation of the object - print(x)'''
        info = f'{self.name}:'
        # These are error/warning messages
        if self._err:
            for errMsg in self._err:
                info += f'\n└ ERROR: {errMsg}'
        return info

    @property
    def err(self):
        '''Return the list of error messages'''
        return self._err

    @err.setter
    def err(self, arg):
        '''Add another string to the error messages'''
        if isinstance(arg, str):
            self._err.append(arg)
        if isinstance(arg, list):
            self._err.extend(arg)

这里是好的 class,其中 err 属性是独一无二的:

>>> import test
>>> a = test.MyHostGood('foo')
>>> a.err = 'Here is one error string'
>>> print(a)
foo:
└ ERROR: Here is one error string
>>> b = test.MyHostGood('bar')
>>> print(b)
bar:
>>> b.err = 'a new error'
>>> print(a)
foo:
└ ERROR: Here is one error string
>>> print(b)
bar:
└ ERROR: a new error
>>>

这里 err 属性现在在对象之间共享:

>>> import test
>>> c = test.MyHostBad('wiz')
>>> c.err = 'Here is one error string'
>>> print(c)
wiz:
└ ERROR: Here is one error string
>>> d = test.MyHostBad('baz')
>>> print(d)
baz:
└ ERROR: Here is one error string
>>> d.err = 'a new error'
>>> print(c)
wiz:
└ ERROR: Here is one error string
└ ERROR: a new error
>>> print(d)
baz:
└ ERROR: Here is one error string
└ ERROR: a new error
>>>

如何修复 getter/setter 以便对象再次拥有自己的错误字符串?

_err是一个class变量,所有对象共享。由于 setter 方法就地修改了它,因此所有对象都可以看到更改。要解决此问题,请通过修改 MyHostBad:

的构造函数使 _err 成为对象属性
def __init__(self, name=''):
    '''Constructor'''
    self.name = name
    self._err = []