真值判斷(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 的自訂。官方文件
---
---
---
沒有留言:
張貼留言