【5】标准类型运算符
-5.1 对象值的比较
比较运算符用来判断同类型对象是否相等,所有的内建类型均支持比较运算,比较运算返回布尔值 True 或 False。早于 Python2.3 的版本,这些版本还没有 布尔类型,所以会看到比较结果为整型值 1 (代表 True)或 0 (代表 False)。
注意,实际进行的比较运算因类型而异。换言之,数字类型根据数值的大小和符号比较, 字符串按照字符序列值进行比较,等等。
3 == 3 # True 3.1 <= 3.8 # True 5 + 4j >= 1- 3j # True 'abc' == 'xyz' #False 'abc' > 'xyz' # False 'abc' < 'xyz' # True [1,'abc] == ['abc', 1] # False [1, 'abc'] == [1, 'abc] # True
多个操作可以在同一行上进行,求值顺序为从左到右。
2 < 4 < 6 # (2 < 4) and (4 < 6) # True 3 < 2 <5 != 3 <6 # False
-5.2 对象身份比较
对象可以被赋值到另一个变量(通过引用)。因为每个变量都指向同一个(共享的)数据对象,只要任何一个引用改变,该对 象的其它引用也会随之改变。
例1:foo1 和foo2 指向相同的对象
foo1 = foo2 = 4.3
当你从值的观点看这条语句时, 它表现的只是一个多重赋值,将 4.3 这个值赋给了 foo1 和foo2 这两个变量。这当然是对的, 不过它还有另一层含义。 事实是一个值为 4.3 的数字对象被创建,然后这个对象的引用被赋值给 foo1 和 foo2, 结果就是 foo1 和 foo2 指向同一个对象。
下图演示了一个对象两个引用
例2:foo1 和foo2 指向相同的对象
foo1 = 4.3
foo2 = foo1
这个例子非常类似上一个,一个值为 4.3 的数值对象被创建,然后赋给一个变量, 当执行 foo2 = foo1 时, foo2 被指向 foo1 所指向的同一个对象, 这是因为 Python 通过传递引用来 处理对象。foo2 就成为原始值 4.3的一个新的引用。 这样 foo1 和 foo2 就都指向了同一个对 象。示意图也和上图一样。
例3:foo1 和 foo2 指向不同的对象
foo1 = 4.3
foo2 = 3.0 + 1.3
这个例子有所不同。首先一个数字对象被创建,然后赋值给 foo1. 然后第二个数值对象被 创建并赋值给 foo2. 尽管两个对象保存的是同样大小的值,但事实上系统中保存的都是两个独 立的对象,其中 foo1 是第一个对象的引用, foo2 则是第二个对象的引用。图 4-2 演示给我 们这里有两个不同的对象,尽管这两个对象有同样大小的数值。 我们为什么在示意图中使用盒 子?没错,对象就象一个装着内容的盒子。当一个对象被赋值到一个变量,就象在这个盒子上 贴了一个标签,表示创建了一个引用。每当这个对象有了一个新的引用,就会在盒子上新贴一 张标签。当一个引用被销毁时, 这个标签就会被撕掉。当所有的标签都被撕掉时, 这个盒子 就会被回收。那么,Python 是怎么知道这个盒子有多少个标签呢?
每个对象都天生具有一个计数器,记录它自己的引用次数。这个数目表示有多少个变量指 向该对象。
Python 提供了 is 和 is not 运算符来测试两个变量是否指向同一个对象。
a = [1,2,3,'python'] b = a a is b # True a is not b # False
标准类型对象身份比较运算符
运算符 | 功能 |
obj1 is obj2 | obj1和obj2是同一个对象 |
obj1 is not obj2 | obj1和obj2不是同一个对象 |
-5.3 布尔类型
布尔逻辑运算符 and, or 和 not 都是 Python 关键字,这些运算符的优先级按从高到低 的顺序列于表 4.3. not 运算符拥有最高优先级,只比所有比较运算符低一级。 and 和 or 运 算符则相应的再低一级。
运算符 | 功能 |
not expr | expr的逻辑非(否) |
expr1 and expr2 | expr1 和expr2的逻辑与 |
expr1 or expr2 | expr1 和expr2的逻辑或 |
if not(2 > 1): print('a') else: print('b') # b x = 10 y = 20 z = 30 if (x < y) or (z < y): print('c') # c if (x < y) and (y < z): print('d') # d
下表表示标准类型内建函数:
函数 | 功能 |
cmp(obj1, obj2) |
i < 0 if obj1 < obj2 i > 0 if obj1 > obj2 i == 0 if obj1 == obj2 |
repr(obj) 或 `obj` | 返回一个对象的字符串表示 |
str(obj) | 返回对象适合可读性好的字符串表示 |
type(obj) |
得到一个对象的类型,并返回相应的 type 对象 |
-6.1 type()
type() 接受一个对象做为参数,并返回它的类型。它的返回值是一个类型对象。
type(1) # <type 'int'> type('python') # <type 'string'> type(type(1)) # <type 'type'>
-6.2 cmp() python3已经对这个函数废除
内建函数 cmp()用于比较两个对象 obj1 和 obj2, 如果 obj1 小于 obj2, 则返回一个负整数,如果 obj1 大于 obj2 则返回一个正整数, 如果 obj1 等于 obj2, 则返回 0。
a, b = 2, 3 cmp(a,b) # -1 b = 2 cmp (a,b) # 0 a, b = 'abc', 'xyz' cmp(a,b) # -23 cmp(b,a) #23
-6.3 str()和repr() (及``运算符)
内建函数 str() 和 repr() 或反引号运算符(``) 可以方便的以字符串的方式获取对象的 内容、类型、数值属性等信息。str()函数得到的字符串可读性好, 而 repr()函数得到的字符 串通常可以用来重新获得该对象, 通常情况下 obj == eval(repr(obj)) 这个等式是成立的。 这两个函数接受一个对象做为其参数, 返回适当的字符串
注:``已经不推荐使用了
str(4+2j) #4+2j str(1) # 1 str str(2e8) #200000000.0 str([0,1,2]) #[0,1,2] repr([0,1,2]) #[0,1,2] `[0,1,2]`
-6.4 type() 和 isinstance()
type()返回任意 Python 对象对象的类型,而不局限于标准类型。
type('') #<class 'str'> s = 'python' type(s) #<class 'str'> type(1) #<class 'int'> type(0+0j) #<class 'complex'> type(0.0) #<class 'float'> type([]) #<class 'list'> type(()) #<class 'tuple'> type({}) #<class 'dis'> type(type) #<class 'type'>
【7】以更新模型为标准类型分类
分类 |
Python 类型 |
可变类型 |
列表, 字典 |
不可变类型 |
数字、字符串、元组 |
通过id()来查看
不可变类型:
s = 'python' print(id(s)) #4325967328 s = 'hello python' print(id(s)) #4369273392 i = 0 print(id(i)) #4305209664 i += 1 print(id(i)) #4305209696
可变类型
aList = ['python',1,2,'hugo'] print(id(aList)) #4369008136 aList[1] = aList[1] + 1 print(aList) #['python', 2, 2, 'hugo'] print(id(aList)) #4369008136
注意:列表的值不论怎么改变, 列表的 ID 始终保持不变。
【8】以访问模型为标准的类型分类
分类 |
Python 类型 |
直接访问 |
数字 |
顺序访问 |
字符串、列表、元组 |
映射访问 |
字典 |