真值判斷(Truth Value Testing)
以下的值在上述三個地方(if、while 與布林運算(Boolean Operation)),會被認為是 False。- None
- False
- 整數 0 與浮點數 0.0
- 空的 sequence,例如空字串、空 list 與空 tuple
- 空的 dict
- 自訂 class,且__bool__() 回傳 False
- 自訂 class,且__len__() 回傳 0
def t_or_f(v): if v: print(True) else: print(False) t_or_f(None) # False t_or_f(False) # False t_or_f(0) # False t_or_f(5) # True t_or_f(0.0) # False t_or_f(0.5) # True t_or_f('') # False t_or_f('A') # True t_or_f([]) # False t_or_f([ 'Neil' ]) # True t_or_f(()) # False t_or_f(( 'Neil' )) # True t_or_f({}) # False t_or_f({ 'name': 'Neil' }) # True class bool_f: def __init__(self, v = False): self.v = v def __bool__(self): return self.v t_or_f(bool_f(False)) # False t_or_f(bool_f(True)) # True class len_f: def __init__(self, v = 0): self.v = v def __len__(self): return self.v t_or_f(len_f(0)) # False t_or_f(len_f(1)) # True
布林運算(Boolean Operation)
布林運算有三個運算子。- and
- or
- not
def bln_and(v, x): if v and x: print(True) else: print(False) def bln_or(v, x): if v or x: print(True) else: print(False) def bln_not(v): if not v: print(True) else: print(False) bln_and(None, False) # False bln_or(None, False) # False bln_and(0, 0.5) # False bln_or(0, 0.5) # True bln_not('') # True bln_not([ 'Neil' ]) # False
相等運算(Comparison Operation)
相等運算有八個運算子。- >
- >=:小心不要用成 =>
- <
- <=:小心不要用成 =<
- ==
- !=
- is:相同的物件參照,適用於 mutable object
- is not:不同的物件參照,適用於 mutable object
運算優先權都相同,也就是遇到這八個運算子時,如果沒有括弧,就是從左算到右。
八個相等運算子的優先權都高於布林運算子。
a = 1 b = 2 print(a == b) # False print(not a == b) # True,等於 not (a == b) print(not (a == b)) # True # print(a == not b) # Invalid Syntax print(False == (not b)) # True用來判斷物件參照的 is 與 is not,要特別小心是不是「mutable」,正常使用方式如下。
a = [] b = a c = [] print(id(a)) # 31564344 print(id(b)) # 31564344 print(id(c)) # 31564144 print(a == b) # True,值相同 print(a is b) # True,參照相同 print(a == c) # True,值相同 print(a is c) # False,參照不同b 參照 a 變數,所以 a 與 b 是參照同一個物件,因此 a is b。
而 c 是另外建立的,雖然內容和 a 相同(因此 a == c),但是參照不同的物件,所以 a is not c。
但是對 immutable 物件來說,Python 為了節省資源,通常會參照相同的物件,不論是如何建立的(甚至是計算或組裝的結果),只要值相同,就會使用相同的物件參照。
a = 256 b = 256 c = 250 + 6 print(id(a)) # 1362847456 print(id(b)) # 1362847456 print(id(c)) # 1362847456 print(a == b) # True print(a is b) # True print(a is c) # True a = 'Hello' b = 'Hello' c = 'He' + 'llo' print(id(a)) # 32444640 print(id(b)) # 32444640 print(id(b)) # 32444640 print(a == b) # True print(a is b) # True print(a is c) # True因此 is 與 is not 只適用於 mutable 物件的「參照」比對,若是「值」的比對,不管是 mutable 或者 immutable,都適用其他六個相等運算子(>、>=、<、<=、==、!=)。
x = 6 y = 7 z = 7 print(x < y) # True print(y <= z) # True print(x < y and y <= z) # True print(x < y <= z) # True, 最不可思議的語法同一個 class 的不同 instance 預設視為不相等(!=),除非 class 定義了__eq__。
class A: def a(): pass a1 = A() a2 = A() print(str(a1) + ' - ' + str(id(a1))) # <__main__.A object at 0x01A2CD70> - 27446640 print(str(a2) + ' - ' + str(id(a2))) # <__main__.A object at 0x01A47690> - 27555472 print(a1 == a2) # False class B: def __init__(self, name): self.name = name; def __eq__(self, other): return self.name == other.name b1 = B('Neil') b2 = B('Neil') b3 = B('Nail') print(str(b1) + ' - ' + str(id(b1))) # <__main__.B object at 0x0151F130> - 22147376 print(str(b2) + ' - ' + str(id(b2))) # <__main__.B object at 0x01EF1DB0> - 32447920 print(str(b3) + ' - ' + str(id(b3))) # <__main__.B object at 0x01EF1E10> - 32448016 print(b1 == b2) # True print(b1 == b3) # False可以依此類推,要對同一個 class 的不同 instance 進行相等運算(Comparison Operation),必須分別定義 __lt__、__le__、__gt__ 與 __ge__,當然還有前面提到的 __eq__ 以及 __ne__。
class C: def __init__(self, age): self.age = age; def __eq__(self, other): return self.age == other.age def __ne__(self, other): return self.age != other.age def __lt__(self, other): return self.age < other.age def __le__(self, other): return self.age <= other.age def __gt__(self, other): return self.age > other.age def __ge__(self, other): return self.age >= other.age c1 = C(2) c2 = C(2) c3 = C(6) print(str(c1) + ' - ' + str(id(c1))) # <__main__.C object at 0x01A3CD70> - 27512176 print(str(c2) + ' - ' + str(id(c2))) # <__main__.C object at 0x01A57690> - 27621008 print(str(c3) + ' - ' + str(id(c3))) # <__main__.C object at 0x01EF13B0> - 32445360 print(c1 == c2) # True print(c1 == c3) # False print(c1 >= c2) # True print(c1 <= c2) # True print(c1 > c3) # False print(c2 < c3) # True print(c1 != c2) # False print(c2 != c3) # True最後,不能也不需要為自訂 class 進行 is 與 is not 的自訂。
官方文件
---
---
---
沒有留言:
張貼留言