1. 程式人生 > 其它 >239.python學習手冊第四版-魔術方法

239.python學習手冊第四版-魔術方法

常用的魔術方法

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"