__init__ 方法在传递 none 时获取值

__init__ method gets a value while none is passed

我有一个classTextBuffer。它有一个 __init__ 函数,可以用来为 TextBuffer 的内容传递一个初始值。如果没有传递任何值,那么它应该使用一个空列表作为默认值。

class有一个方法add,为了向TextBuffer添加文本:

a = TextBuffer()
a += "TEXT"

出于某种原因,调用不带参数的__init__方法不会使用lst的默认值[],而是使用先前添加到[=15]的另一个实例的值=],它不在 __init__ 调用

a = TextBuffer()
a += "BUFFER A"
b = TextBuffer()  ### lst in the __init__ call has the value of ["BUFFER A"]
b += "BUFFER B"

我不知道为什么会这样。也许我在 __add__ 方法中做错了什么?

请考虑完整的示例代码:

import pprint

### Two functions for byte/string conversion in Python3
def b(x):
    if ( type(x) == type(b'')):
        return x
    else:
        return x.encode(encoding='UTF-8')
def s(x):
    if ( type(x) == type(b'') ):
        return x.decode(encoding='UTF-8')
    else:
        return x


class TextBuffer():
    def __init__( self, lst = [], maxlines = None ):
        self.content = []
        if ( type(lst) == type([])):
            if (len(lst) > 0):
                print("INIT got a nonempty lst value:")
                pprint.pprint(lst)
                print("------------------------------")
            self.content = lst


    def __getitem__( self, i ):
        try:
            return self.content[i]
        except IndexError:
            return None

    def __iter__( self ):
        for line in self.content:
            yield line

    def __contains__( self, item ):
        return item in self.content

    def __len__( self ):
        return len(self.content)

    def __add__( self, item ):
        self.content.append(item)
        return self

    def __radd__( self, item ):
        return self.__add__(item)

    def __repr__( self ):
        result = ""
        for line in self.content:
            if ( type(line) == type(b"") ):
                result+=s(line)
            else:
                result+=line
        return result

    def __str__( self ):
        return repr(self)

    def __unicode__( self ):
        return repr(self.content)

### TextBuffer INIT with empty list creates an empty textbuffer
a = TextBuffer(lst=[])
print("a = TextBuffer(lst=[])")

a += "BUFFER A"


### TextBuffer INIT with empty list creates an empty textbuffer
b = TextBuffer(lst=[])
print("b = TextBuffer(lst=[])")

b += "BUFFER B"

print("Content of TextBuffer a:")
print(a)
print("Content of TextBuffer b:")
print(b)

print("-------------------------")

### TextBuffer INIT without any parameters should use default value for lst of []
### So an empty list. Should be the same as TextBuffer(lst=[])
a = TextBuffer()
print("a = TextBuffer()")

a += "BUFFER A"

### TextBuffer INIT without any parameters should use default value for lst of []
### So an empty list. Should be the same as TextBuffer(lst=[])
### But now, the value of lst is not [], it is the string added to TextBuffer 'a': ['BUFFER A']
b = TextBuffer()
print("b = TextBuffer()")

b += "BUFFER B"

print("Content of TextBuffer a:")
print(a)
print("Content of TextBuffer b:")
print(b)

在这种情况下,您不能使用 lst = [] 作为默认参数 ,因为 Python 将 生成一个列表 在内存中,每次 将对同一对象(列表)的引用 传递给构造函数。这意味着您的两个对象共享相同的 lst,因此一个对象所做的修改会反映在另一个对象中,反之亦然。

您可以使用以下技巧:

def __init__( self, lst = None, maxlines = None ):
    if lst is None:
        lst = []
    #... (remainder of the constructor)

因为在这里你强制Python构建一个新列表。显然你可以使用 None 之外的其他值;但我认为对于你的情况这就足够了。

一般来说,不要可变对象作为默认值是个好主意,始终使用不可变对象。然而,@hiroprotagonist 描述了需要这种行为的情况(如记忆),但我建议对这些情况非常小心。