我有一个班级TextBuffer
。它具有__init__
函数,可用于传递TextBuffer
内容的初始值。如果没有传递任何值,那么它应该使用空列表作为默认值。
该类有一个方法添加,以便向TextBuffer添加文字:
a = TextBuffer()
a += "TEXT"
出于某种原因,调用不带参数的__init__
方法不会将[]
的默认值用于lst
,而是先前为TextBuffer
的另一个实例添加的值,不在__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)
答案 0 :(得分:2)
在这种情况下,您无法使用lst = []
作为默认参数,因为Python会在内存中生成一个列表,并且每次引用时都会传递构造函数的相同对象(列表)。这意味着您的两个对象共享相同的lst
,因此一个对象所做的修改会反映在另一个对象中,反之亦然。
您可以使用以下技巧:
def __init__( self, lst = None, maxlines = None ):
if lst is None:
lst = []
#... (remainder of the constructor)
因为在这里你迫使Python 构建一个新列表。显然你可以使用另一个值None
;但我想你的情况就足够了。
一般来说,不将可变对象作为默认值提交,总是使用不可变对象。但是,正如@hiroprotagonist描述了需要这种行为的情况(如记忆),但我建议对这些行为要非常小心。