标签:
python中有一些容易忽略的不可变类型(str,integer,tuple,None)
#错误演示
In [45]: def demo(lst=[]): ....: lst.append("hello") ....: return lst ....: In [46]: demo() Out[46]: [‘hello‘] In [47]: demo() Out[47]: [‘hello‘, ‘hello‘]
廖雪峰的python教程有提到这一块,但并没有太细致。在这里,由于lst是一个可变参数,而demo在初始化时lst参数指向一个[]的内存空间,之后每一次调用,[]这个内存空间都append一个“hello”,而由于lst依然指向这个内存空间,所以就会看到demo函数调用的奇怪现象,解决问题的办法就是引入不可变类型。
#正确演示 In [54]: def demo(lst=None): ....: lst=[] ....: lst.append("hello") ....: return lst ....: In [55]: demo() Out[55]: [‘hello‘] In [56]: demo() Out[56]: [‘hello‘]
在正确演示中,将lst初始化为None,这样lst就是一个不可变参数,但是不能直接对lst直接使用append,因为只有list才有append方法,因此需要将lst进行真正的初始化:lst=[]
在这里,我还想延伸一下关于__new__的用法。为什么要放在这里说,待会看了这个例子就会明白。
class Word(str): def __new__(cls, word): word = word.replace(" ","") return str.__new__(cls,word) def __init__(self,word): self.word = word
def __eq__(self, other): return len(self)==len(other)
def main(): a=Word("foorrrdd ") b=Word("sswwss ") print a==b
if __name__ == ‘__main__‘: main()
在这段代码里,可以看到Word类继承自str,str是一个不可变类型,因此需要使用到__new__这个魔术方法,在这里对word这个形参进行了预处理,然后预处理后的形参word会传递给__init__。由于此例此种情形中,a,b指向的是不同的内存空间,即使不用__new__也不会因为实参的传入导致上面例子出现不断追加的情况,但显然这会是一种更为安全的写法。
(ps:我不是很确定None是不是一个不可变类型,这篇文章只是个人的理解,如果有误,恳请指正。)
标签:
原文地址:http://www.cnblogs.com/alexkn/p/4657306.html