社區專欄>python中一些特殊方法的自定義及作用>
引言
1 2 3
|
聊一聊__add__,__mul__,__len__,__bool__的作用和自定義,以及__len__和 __bool__是怎么影響if/while的條件判斷,另外說一說怎么把一個對象以字符串的 形式表現。
|
自定義運算符
使用場景
1 2
|
自定義一個類, 類中有兩個屬性分別為x和y, 實現a+b a*b的功能,要求a+b實現a.x+b.x a.y+b.y; a*b實現a.x*b.x a.y*b.y
|
實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
class V(object):
def __init__(self, x, y): self.x = x self.y = y
def __add__(self, v): print('run __add__') return V(x=v.x + self.x, y=v.y + self.y)
def __mul__(self, v): print('run __mul__') return V(x=v.x * self.x, y=v.y * self.y)
v = V(1, 2) print('---------------add----------') new_v = v + v print(new_v.x)
print('---------------mul----------') new_v = v * v print(new_v.y)
|
自定義bool值
關于if v
1 2 3
|
默認情況下我們自己定義的類的實例總是被認為時真的,但是有的時候這個默認值不是我們想要的, 除非我們自己定義__bool__或者__len__才能實現我們想要的結果,我們還以剛才的類V舉例, 我想你總不希望當x和y都是0的時候還希望if v成立吧
|
關于bool()
1 2 3
|
像if v/if not v等,python會調用bool(v)方法,而bool(v)背后的調用時嘗試調用 v.__bool__(),如果沒有__bool__方法,就會嘗試調用__len__方法,若這是返回0則 是False否則為True,這兩個方法都沒有的話只能按照默認處理了
|
實現
bool和len都沒有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class V(object):
def __init__(self, x, y): self.x = x self.y = y
v = V(1, 2)
print('--------------if----------') if v: print('\tif True') else: print('\tif False')
print('-------------while----------') while v: print('\twhile True') break 執行結果: --------------if---------- if True -------------while---------- while True
|
只有len
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
class V(object):
def __init__(self, x, y): self.x = x self.y = y
def __len__(self): print('run __len__') return self.x + self.y
v = V(1, 2)
print('--------------if----------') if v: print('\tif True') else: print('\tif False')
print('-------------while----------') while v: print('\twhile True') break
執行結果: --------------if---------- run __len__ if True -------------while---------- run __len__ while True
|
bool與len都有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
class V(object):
def __init__(self, x, y): self.x = x self.y = y
def __bool__(self): print('run __bool__') return bool(self.x or self.y)
def __len__(self): print('run __len__') return self.x + self.y
v = V(1, 2)
print('--------------if----------') if v: print('\tif True') else: print('\tif False')
print('-------------while----------') while v: print('\twhile True') break
執行結果: --------------if---------- run __bool__ if True -------------while---------- run __bool__ while True
|
如何使對象以字符串的形式表現
為什么要以字符串的形式
1 2 3
|
我們把一個對象以字符串的形式表現出來,是為了更好的辨認,方便后續處理或讓用戶覺得更加直觀, 最普遍的是在django的admin中,我們希望看到一行數據的誰的數據,而不是希望看到一個class 或其他無法辨識的表現形式。
|
只用str實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
class Student(object):
def __init__(self, name): self.name = name
def __str__(self): print('\t-------------call __str__-------------\n') return self.name
s = Student('baisong') print('------ s is:', s)
print('---str--- s is:', str(s))
print('---repr---s is:', repr(s))
執行結果: ------ s is: -------------call __str__-------------
baisong
-------------call __str__-------------
---str--- s is: baisong
---repr---s is: <__main__.Student object at 0x7f64d6fedd30>
|
只用repr實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
class Student(object):
def __init__(self, name): self.name = name
def __repr__(self): print('\tcall __repr__') print('\t-------------call __str__-------------\n') return self.name
s = Student('baisong') print('------ s is:', s)
print('---str--- s is:', str(s))
print('---repr---s is:', repr(s))
執行結果: ------ s is: call __repr__ -------------call __str__------------- baisong
call __repr__ -------------call __str__------------- ---str--- s is: baisong
call __repr__ -------------call __str__------------- ---repr---s is: baisong
|
repr與str的不同
1 2 3 4 5
|
從上邊例子可以看出來__repr__與__str__的區別在于,后者實在str()被使用, 或者在 print的時候調用, __str__返回的字符串對于終端用戶更友好。而__repr__是由python 的內置函數repr調用, 如果說你只想用其中的一個,建議使用__repr__, 因為python解釋 器會在沒有__str__的時候用__repr__代替(前邊的例子print已經展示出來), 讀者可以自 己試試當__repr__與__str__都存在的輸出結果。
|