Python-魔法方法詳解(二)

__add__

定義加號的操作,即當使用+操作時,將會觸發__add__()方法。舉個栗子:

class Student(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __add__(self, other):
        print("__add__", self.age, other.age)
        return self.age + other.age
        
s1 = Student("laowang", 18)
s2 = Student("laozhang", 20)
print(s1 + s2)

############## 打印結果如下 ##############
__add__ 18 20
38

__radd__

__radd__()__add__()方法一樣,都是定義加號的操作時纔會觸發!但是__add__()方法的“優先級較高”,比如說x + yxy是兩個類的不同的實例,如果x未重寫__add__()方法,那麼將會調用y__radd__()方法。舉個栗子:

class Student(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __radd__(self, other):
        print("student __radd__", self.age, other.age)
        return self.age + other.age
        
class Teacher(object):

    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __radd__(self, other):
        print("teacher __radd__", self.age, other.age)
        return self.age + other.age

s = Student("laozhang", 18)
t = Teacher("laowang", 20)
print(s + t)
print(t + s)

############## 打印結果如下 ##############
teacher __radd__ 20 18
38
student __radd__ 18 20
38

值得注意的是,所有的二元運算符都有右側重載方法(例如,__radd____rsub__等),只有滿足以下兩種條件時,纔會觸發:

  • 兩個操作數類型不同
  • 左側操作方法沒有重寫

舉個栗子:

class Student(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __radd__(self, other):
        print("student __radd__", self.age, other.age)
        return self.age + other.age

s1 = Student("laowang", 18)
s2 = Student("laozhang", 20)
print(s1 + s2)

############## 打印結果如下 ##############
Traceback (most recent call last):
  ...
TypeError: unsupported operand type(s) for +: 'Student' and 'Student'

s1與s2屬於同一個類型的實例,並且左側操作方法沒有重寫,所以是不允許的!

__sub__

定義減號的操作,即當使用-操作時,將會觸發__sub__()方法。舉個栗子:

class Student(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __sub__(self, other):
        print("__sub__", self.age, other.age)
        return self.age - other.age
        
s1 = Student("laowang", 18)
s2 = Student("laozhang", 20)
print(s1 - s2)

############## 打印結果如下 ##############
__sub__ 18 20
-2

__rsub__

__sub__()的右側重載方法

__mul__

定義乘號的操作,即當使用*操作時,將會觸發__mul__()方法。舉個栗子:

class Student(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __mul__(self, other):
        print("__mul__", self.age, other.age)
        return self.age * other.age
        
s1 = Student("laowang", 3)
s2 = Student("laozhang", 6)
print(s1 * s2)

############## 打印結果如下 ##############
__mul__ 3 6
18

__rmul__

__mul__()的右側重載方法

__truediv__

定義除號的操作,即當使用/操作時,將會觸發__truediv__()方法。舉個栗子:

class Student(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __truediv__(self, other):
        print("__truediv__", self.age, other.age)
        return self.age / other.age
        
s1 = Student("laowang", 3)
s2 = Student("laozhang", 6)
print(s1 / s2)

############## 打印結果如下 ##############
__truediv__ 3 6
0.5

__rtruediv__

__truediv__()的右側重載方法

__floordiv__

定義整數除法的操作,即當使用//操作時,將會觸發__floordiv__()方法。舉個栗子:

class Student(object):

    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __floordiv__(self, other):
        print("__floordiv__", self.age, other.age)
        return self.age // other.age
        
s1 = Student("laowang", 3)
s2 = Student("laozhang", 6)
print(s1 // s2)

############## 打印結果如下 ##############
__floordiv__ 3 6
0

__rfloordiv__

__floordiv__()的右側重載方法

__mod__

定義取模的操作,即當使用%操作時,將會觸發__mod__()方法。舉個栗子:

class Student(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __mod__(self, other):
        print("__mod__", self.age, other.age)
        return self.age % other.age

s1 = Student("laowang", 3)
s2 = Student("laozhang", 6)
print(s1 % s2)

############## 打印結果如下 ##############
__mod__ 3 6
3

__rmod__

__mod__()的右側重載方法

__divmod__

divmod()函數被調用時,將會觸發__divmod__()方法。舉個栗子:

class Student():

    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __divmod__(self, other):
        print("__divmod__", self.age, other.age)
        return self.age // other.age, self.age - (self.age // other.age) * other.age
        
s1 = Student("laowang", 3)
s2 = Student("laozhang", 6)
print(divmod(s1, s2))

############## 打印結果如下 ##############
__divmod__ 3 6
(0, 3)

__rdivmod__

__divmod__()的右側重載方法

__pow__

pow()函數被調用,或使用冪運算**時,將會觸發__pow__()方法。舉個栗子:

class Student(int):

    def __pow__(self, power, modulo=None):
        print("__pow__", self, power, modulo)
        return 0

s1 = Student(3)
s2 = Student(2)
print(pow(s1, s2))
print(s1 ** s2)

############## 打印結果如下 ##############
__pow__ 3 2 None
0
__pow__ 3 2 None
0

__rpow__

__pow__()的右側重載方法

__lshift__

定義左位移的操作時,即當使用<<操作時,將會觸發__lshift__()方法。

__rlshift__

__lshift__()的右側重載方法

__rshift__

定義右位移的操作時,即當使用>>操作時,將會觸發__rshift__()方法。

__rrshift__

__rshift__()的右側重載方法

__and__

定義按位與的操作時,即當使用&操作時,將會觸發__and__()方法。

__or__

定義按位或的操作時,即當使用|操作時,將會觸發__or__()方法。

__ror__

__or__()的右側重載方法

__xor__

定義按位異或的操作時,即當使用^操作時,將會觸發__xor__()方法。

__rxor__

__xor__()的右側重載方法

__iadd__

定義賦值加法的操作,即當使用+=操作時,將會觸發__iadd__()方法。舉個栗子:

class Student(int):

    def __iadd__(self, other):
        print("__iadd__", self, other)
        return self + other
        
s1 = Student(1)
s2 = Student(2)
s1 += s2

############## 打印結果如下 ##############
__iadd__ 1 2

__isub__

定義賦值減法的操作,即當使用-=操作時,將會觸發__isub__()方法。舉個栗子:

class Student(int):

    def __isub__(self, other):
        print("__isub__", self, other)
        return self + other
        
s1 = Student(1)
s2 = Student(2)
s1 -= s2

############## 打印結果如下 ##############
__isub__ 1 2

__imul__

定義賦值乘法的操作,即當使用*=操作時,將會觸發__imul__()方法。舉個栗子:

class Student(int):

    def __imul__(self, other):
        print("__imul__", self, other)
        return self * other
        
s1 = Student(3)
s2 = Student(2)
s1 *= s2

############## 打印結果如下 ##############
__imul__ 3 2

__itruediv__

定義賦值除法的操作,即當使用/=操作時,將會觸發__itruediv__()方法。舉個栗子:

class Student(int):

    def __itruediv__(self, other):
        print("__itruediv__", self, other)
        return self / other
        
s1 = Student(4)
s2 = Student(2)
s1 /= s2

############## 打印結果如下 ##############
__itruediv__ 4 2

__ifloordiv__

定義賦值整數除法的操作,即當使用//=操作時,將會觸發__ifloordiv__()方法。舉個栗子:

class Student(int):

    def __ifloordiv__(self, other):
        print("__ifloordiv__", self, other)
        return self // other
        
s1 = Student(4)
s2 = Student(2)
s1 //= s2

############## 打印結果如下 ##############
__ifloordiv__ 4 2

__imod__

定義賦值取模的操作,即當使用%=操作時,將會觸發__imod__()方法。舉個栗子:

class Student(int):

    def __imod__(self, other):
        print("__imod__", self, other)
        return self % other
        
s1 = Student(3)
s2 = Student(4)
s1 %= s2

############## 打印結果如下 ##############
__imod__ 3 4

__ipow__

定義賦值冪運算的操作,即當使用**=操作時,將會觸發__ipow__()方法。舉個栗子:

class Student(int):

    def __ipow__(self, other):
        print("__ipow__", self, other)
        return 0
        
s1 = Student(3)
s2 = Student(2)
s1 **= s2

############## 打印結果如下 ##############
__ipow__ 3 2

__ilshift__

定義賦值左位移的操作,即當使用<<=操作時,將會觸發__ilshift__()方法。

__irshift__

定義賦值右位移的操作,即當使用>>=操作時,將會觸發__rshift__()方法。

__iand__

定義賦值按位與的操作,即當使用&=操作時,將會觸發__iand__()方法。

__ior__

定義賦值按位或的操作,即當使用|=操作時,將會觸發__ior__()方法。

__ixor__

定義賦值按位異或的操作,即當使用^=操作時,將會觸發__ixor__()方法。

__neg__

定義使用負號的操作,即當使用-操作時,將會觸發__neg__()方法。舉個栗子:

class Student(int):

    def __neg__(self):
        print("__neg__")
        return 0
        
s = Student(3)
print(-s)

############## 打印結果如下 ##############
__neg__
0

__pos__

定義使用正號的操作,即當使用+操作時,將會觸發__pos__()方法。舉個栗子:

class Student(int):

    def __pos__(self):
        print("__pos__")
        return 0
        
s = Student(3)
print(+s)

############## 打印結果如下 ##############
__pos__
0

值得注意的是,當我們使用雙負號操作即--時,雖然我們常說負負得正,但是最終觸發的是__neg__()方法。如下:

class Student(int):
    
    def __neg__(self):
        print("__neg__")
        return 0
        
    def __pos__(self):
        print("__pos__")
        return 0
        
s = Student(2)
print(--s)

############## 打印結果如下 ##############
__neg__
0

__abs__

當我們使用絕對值操作,即調用abs()函數時,將會觸發__abs__()方法。舉個栗子:

class Student(int):
    
    def __abs__(self):
        print("__abs__")
        return 0
        
s = Student(3)
print(abs(s))

############## 打印結果如下 ##############
__abs__
0

invert

當我們使用取反運算(所謂取反運算就是將每個二進制位取反,即將1變爲0,將0變爲1)時,即使用~操作的時候,將會觸發__invert__()方法。舉個栗子:

class Student(int):
    
    def __invert__(self):
        print("__invert__")
        return 0
        
s = Student(3)
print(~s)

############## 打印結果如下 ##############
__invert__
0

__complex__

當調用complex()函數時,將會觸發__complex__()方法。

__int__

當調用int()函數時,將會觸發__int__()方法。舉個栗子:

class Student(str):

    def __int__(self):
        print("__int__")
        return 0

s = Student("3")
print(int(s))

############## 打印結果如下 ##############
__int__
0

值得注意的是,重寫了該方法後需返回一個對應類型的值!

__float__

當調用float()函數時,將會觸發__float__()方法。舉個栗子:

class Student(str):

    def __float__(self):
        print("__float__")
        return 0.1
        
s = Student("3")
print(float(s))

############## 打印結果如下 ##############
__float__
0.1

值得注意的是,重寫了該方法後需返回一個對應類型的值!

__round__

當調用round()函數時,將會觸發__round__()方法。舉個栗子:

class Student(float):

    def __round__(self, n=None):
        print("__round__", n)
        return 0.1
        
s = Student(0.035)
print(round(s))
print(round(s, 2))

############## 打印結果如下 ##############
__round__ None
0.1
__round__ 2
0.1

__index__

當對象用於切片的下標時,將會觸發對象的__index__()方法。舉個栗子:

class Student(float):

    num = 1
    
    def __index__(self):
        print("__index__")
        return self.num

l = [1, 2, 3, 4]        
s = Student(3.33)
print(l[:s])

############## 打印結果如下 ##############
__index__
[1]

值得注意的是,__index__()方法必須返回的是一個整形數據!

__enter__

當使用with操作的時候,將會觸發__enter__()方法,表示進入一段代碼塊,as緊挨着的變量爲__enter__()方法返回的值。舉個栗子:

class Student(object):
    
    def __enter__(self):
        print("__enter__")
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("__exit__")
        
with Student() as s:
    print(s)

############## 打印結果如下 ##############  
__enter__
None
__exit__

我們修改一下上面的代碼,使__enter__()方法返回當前對象,如下:

class Student(object):
    
    def __enter__(self):
        print("__enter__")
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("__exit__")
        
with Student() as s:
    print(s)

############## 打印結果如下 ##############   
__enter__
<__main__.Student object at 0x109d9b588>
__exit__

值得注意的是,如果你重寫了__enter__()方法,那麼就一定要重寫__exit__()方法,它們倆是成雙成對出現的!

__exit__

當一段代碼塊執行完畢時,將會觸發__exit__()方法,通常用於處理對代碼塊的收尾工作!舉個栗子:

class MyFile(object):

    def __enter__(self):
        print("__enter__")
        self.f = open("my_file.txt", "w")
        return self.f
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("__exit__")
        self.f.close()
        
with MyFile() as mf:
    mf.write("hhhhh")
 
############## 打印結果如下 ##############    
__enter__
__exit__

__getitem__

當獲取一個容器元素的操作時,將會觸發__getitem__()方法。舉個栗子:

class Student(list):
    
    def __getitem__(self, item):
        print("__getitem__", self, item)
        return item
        
s = Student([1, 2, 3, 4])
print(s[0])

############## 打印結果如下 ##############  
__getitem__ [1, 2, 3, 4] 0
0

__setitem__

當修改容器元素的值時,將會觸發__setitem__()方法。舉個栗子:

class Student(list):

    def __setitem__(self, key, value):
        print("__setitem__", self, key, value)
        
s = Student([1, 2, 3, 4])
s[0] = 11

############## 打印結果如下 ############## 
__setitem__ [1, 2, 3, 4] 0 11

__delitem__

當刪除容器元素時,將會觸發__delitem__()方法。舉個栗子:

class Student(list):

    def __delitem__(self, key):
        print("__delitem__", self, key)
        
s = Student([1, 2, 3, 4])
del s[0]

############## 打印結果如下 ############## 
__delitem__ [1, 2, 3, 4] 0

__iter__

當迭代容器元素時,將會觸發__iter__()方法。舉個栗子:

class Student(list):

    def __iter__(self):
        print("__iter__")
        return super(Student, self).__iter__()
        
s = Student([1, 2, 3, 4])
for i in s:
    print(i)

############## 打印結果如下 ##############  
__iter__
1
2
3
4

__reversed__

當調用reversed()函數時,將會觸發__reversed__()方法。舉個栗子:

class Student(list):
    
    def __reversed__(self):
        print("__reversed__")
        return super(Student, self).__reversed__()
        
s = Student([1, 2, 3, 4])
reversed(s)

############## 打印結果如下 ##############
__reversed__

__contains__

當使用in來判斷元素是否存在於容器中的操作時,將會觸發__contains__()方法。舉個栗子:

class Student(list):

    def __contains__(self, item):
        print("__contains__", self, item)
        return super(Student, self).__contains__(item)
        
s = Student([1, 2, 3, 4])
print(1 in s)

############## 打印結果如下 ##############
__contains__ [1, 2, 3, 4] 1
True

至此Over~~~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章