newsim
- UID
- 10355
- 帖子
- 96
- 积分
- 220
- 在线时间
- 12 小时
|
1#
newsim 发表于 2006-02-25 01:24
python(12): 比较、真值等杂项
在python中,一切变量都是引用变量。这有时候非常有用,但有时候也会造成麻烦。比如:
- >>> L = [1, 2]
- >>> X = [0, L, 3]
在这上面的情况下,如果在后面的程序中改变了L的内容,那么由于X保存的是L的引用,那么X中的内容也会变。这可能不是所想要了。解决这个问题可用如下方式:
L[:]会返回一个新的list,因此可以避免这个问题。对于没有”分片“功能的dictionary可以使用它的专属函数copy()来返回一个新的dictionary。设想一下:
- >>> L = [0, [1, 2, 3], 4]
- >>> X = ['A', L[:], 5]
- >>> L[1][1]= 'B'
现在X的值是什么呢?我们慢慢来分析,首先X中保存的是什么呢?第一个毫无疑问是指向对象'A'的指针,第三个也就是指向对象5的指针。关健是第二个,L中保存有指向3 [1,2,3] 4的指针,”分片“会返回新的对象,因此L[:]的过程是
把L中第一个指针指向的内容也就是0复制一份,把其地址作为返回list的第一个值
- 把L中第二个指针指向的内容也就是保存有[1,2,3]中对象1 2 3的指针也复制一份,作为返回list的第二个值返回
- 把L中第三个指针指向的内容也就是4复制一份,作为返回list的第三个值返回从第2步可以看出,复制的仅仅是指向[1,2,3]中的1 2 3的指针,而不是1 2 3本身,因此虽然保存在L和X中第二个成员的指针是不相等的,但是这两个指针指向的list中保存的内容是一致的,都指向了相同的 1 2 3对象。因此改变了[1,2,3]中的成员,X中相应的地方也会变,即X现在为['A', [0, [1, 'B', 3], 4], 5]。
由此可见用L[:]方式产生一个新的list是不完全的拷贝,类似的dictionary也是不完全的拷贝。它只拷贝了第一层,如果需要完全的拷贝,那么就要用到copy这个模块。
- >>> import copy
- >>> copy.deepcopy(L)这样就可以产生一个完全L的拷贝。
在python中有两种比较相等于的运算符一个是==,另一个是is。他们之间是有区别的,==用于比较内容是否相同,is比较是否是同一对象。比如:
- >>> one = "hello world"
- >>> two = "hello world"
- >>> one == two, one is two
- (1,0)这里的1代表真值,0代表假值。在python中真值可以用True表示,False表示假。None以及所有空的对象都表示假。其他为真。此外,由于python优化的原因,python会重用短的string和小整数,如果在这里测试的string过短可能会产生(1,1)的结果。
在python中一切都是对象(这好像是第三次写到这句话了)。内置函数type(object)可以回object的类型信息。isinstance(object, types or tuple of types)可以用来比较object是否是第二能数中标明的类型。在types中还定义了好多类型的名字,比如list有别名ListType,dict有DictType,type有TypeType等等。以前一直以为在types模块中再设一些别名是多此一举,不过认真想了一想,发现这有其自己的逻辑。假设要判断一个对象object是不是str类型。可惟采用下面的方法:
- isinstance(object, str)
- type(object) == type(str())
- type(object) == types.StringType第一种方法看起来好像很简便很直观,可以直接用类型名list来表示list。但这也正是它的弱点,比如说原来string的名字是叫string,如果原来程序上写的是isinstance(object, string),那么这个语句在现在就已经不适用。第二种方法绕的弯太多,也存在像第一种方法的问题。只有第三种方法,由于在真实的类型名上加了一个映射层,不管真实的string类型名字怎么变,StringType就是代表string类型。可以克服前两种方法的缺陷。而且由于存在一个映射过程,可以自己来控制这个过程,如果你想这么干,完全可以用StringType代表int型。
如果一个list把它本身作为一个成员就会出现无限循环的情况,在python用[...]来表示无限循环,一般应该避免出现这种情况。tuple dictionary也有类似的情况
|