__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 描述了需要这种行为的情况(如记忆),但我建议对这些情况非常小心。
我有一个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 描述了需要这种行为的情况(如记忆),但我建议对这些情况非常小心。