239.python學習手冊第四版-魔術方法
阿新 • • 發佈:2022-06-05
常用的魔術方法
class DictC: def __setitem__(self, key, value): """當通過字典方式賦值是呼叫, 比如a["abc"]=1""" print("__setitem__") # self.key = value # 這種方式會呼叫__setattr__方法 self.__dict__[key] = value def __getitem__(self, item): """當通過字典方式取值時呼叫, 比如a["abc"]""" print(getattr(self, item)) return self.__dict__[item] if __name__ == '__main__': d = DictC() d["a"] = 1 print(d["a"]) class SkipIterator: def __init__(self, wrapped): self.wrapped = wrapped self.offset = 0 def __next__(self): """呼叫next方法時呼叫""" if self.offset >= len(self.wrapped): raise StopIteration else: item = self.wrapped[self.offset] self.offset += 2 return item class SkipObject: def __init__(self, wrapped): self.wrapped = wrapped def __iter__(self): return SkipIterator(self.wrapped) # if __name__ == '__main__': # skiper = SkipObject("abcdef") # I = iter(skiper) # print(next(I)) # print(next(I)) # print(next(I)) # for x in skiper: # for y in skiper: # print(x + y, end=" ") class Iters: def __init__(self, value): self.data = value def __getitem__(self, item): """當不存在__iter__方法時呼叫, 優先順序__contains__ > __iter__ > __getitem__""" print("get[%s] :" % item, end=" ") return self.data[item] def __iter__(self): """當呼叫iter方法時, 返回一個可迭代物件, 之後呼叫__next__方法遍歷元素""" print("iter =>", end=" ") self.ix = 0 return self def __next__(self): """當呼叫next方法時執行, for迴圈自動呼叫__next__方法""" print("next:", end=" ") if self.ix == len(self.data): raise StopIteration item = self.data[self.ix] self.ix += 1 return item # def __contains__(self, item): # print("contains: ", end=" ") # return item in self.data # if __name__ == '__main__': # x = Iters([1, 2, 3, 4, 5]) # print(3 in x) # for i in x: # print(i, end=" ") # print() # print([i ** 2 for i in x]) # print(list(map(bin, x))) # I = iter(x) # while True: # try: # print(next(I), end=" @ ") # except StopIteration: # break # x = Iters("spam") # print(x[0]) # print("spam"[1:]) # print("spam"[slice(1, None)]) # print(x[1:]) # print(x[:-1]) class Empty: # .age 點語法取值時執行 def __getattr__(self, item): if item == "age": return 40 else: raise AttributeError(item) # .age=12, 點語法賦值時執行 def __setattr__(self, key, value): if key == "age": self.__dict__[key] = value else: raise AttributeError(key + " not allowed") # if __name__ == '__main__': # e = Empty() # # print(e.age) # # print(e.name) # e.age = 40 # e.name = "mel" class Commuter: def __init__(self, val): self.val = val def __add__(self, other): """左加法, 當前物件在左邊時執行, 比如c = Commuter(0) c + 10""" print("__add__ 左加法") if isinstance(other, Commuter): other = other.val return Commuter(self.val + other) def __radd__(self, other): """右加法, 當前物件在右邊時執行, 比如c = Commuter(0) 10 + c""" print("__radd__ 右加法") return Commuter(other + self.val) def __str__(self): return '<Commuter: %s>' %self.val class Number: def __init__(self, val): self.val = val def __add__(self, other): """左加法, 當前物件在左邊時執行, 比如c = Commuter(0) c + 10""" print("__add__ 左加法") if isinstance(other, Commuter): other = other.val return Number(self.val + other) def __iadd__(self, other): """原地加法, __iadd__不存在時執行__add__""" print("__iadd__ 原地加法") self.val += other return self # if __name__ == '__main__': # x = Commuter(88) # y = Commuter(99) # print(x + 10) # print(10 + y) # # z = x + y # print(z) # print(z + 10) # print(z + z) # n = Number(5) # n += 1 # n += 1 # print(n.val) class Mul: def __init__(self, val): self.val = val def __mul__(self, other): """乘法類似於__add__方法, __rmul__, __imul__""" print("__mul__ ") self.val *= other return self.val # if __name__ == '__main__': # mul = Mul(10) # mul * 9 # print(mul.val) class Callee: def __call__(self, *args, **kwargs): """類例項物件加()時呼叫, c = Callee(), c(1, 2, 3)""" print("called: ", args, kwargs) class Prod: def __init__(self, val): self.val = val def __call__(self, other): return self.val * other # if __name__ == '__main__': # c = Callee() # c(1, 2, 3) # c(1, 2, 3, x=7, y=8) # p = Prod(4) # print(p(5)) class Callback: def __init__(self, color): self.color = color def __call__(self): print("turn", self.color) class Button: def __init__(self, command): self.command = command # if __name__ == '__main__': # cb1 = Callback("blue") # cb2 = Callback("green") # # b1 = Button(command=cb1) # b2 = Button(command=cb2) # # print(cb1()) # print(cb2()) # cb3 = lambda color="red": "turn " + color # print(cb3()) class C: data = "spam" def __gt__(self, other): """大於""" return self.data > other def __lt__(self, other): """小於""" return self.data < other """ __cmp__方法已經在python3中刪除 """ # if __name__ == '__main__': # c = C() # print(c > "ham") # print(c < "ham") class Truth: def __bool__(self): """ python3: 判斷當前物件bool屬性, 沒有__bool__方法時執行__len__方法 python3: 判斷當前物件bool屬性, 將__bool__方法替換成__nonzero__方法即可, 其他類似python3 """ return True def __len__(self): return 0 # if __name__ == '__main__': # t = Truth() # if t: # print("yes!") class Life: def __init__(self, name="unknown"): print("hello ", name) self.name = name def __del__(self): """物件引用清空被回收時執行, 解構函式__del__ 比如 brain = "loretta"會導致life無引用, 此時觸發__del__ """ print("__del__ ", self.name) print("Goodbye", self.name) # if __name__ == '__main__': # brain = Life("brain") # brain = "loretta"