美文网首页Python
Python 魔术方法

Python 魔术方法

作者: 星光下的胖子 | 来源:发表于2021-01-31 13:38 被阅读0次
    You'll miss 100% of shots you don't take.

    一、魔术方法简介

    Python 中所有以双下划线“__”包起来的方法,统称为“Magic Method”(魔术方法)

    魔术方式是 Python 的内置方法,不需要主动调用,当我们对实例调用某些特定函数或运算符时,会自动触发。例如最常见的 __new____init__:当调用 p = Person() 时,首先触发 __new__ 创建一个 instance 并返回,然后触发 __init__ 用传入的参数对 instance 进行初始化。

    Python 的魔术方法有很多,下面介绍一些常见的魔术方法。

    二、常见的魔术方法及代码示例

    1.实例生命周期、允许实例像函数一样被调用
    __new__(cls)、__init__(self):创建实例、实例初始化的时候触发
    __del__(self):销毁实例的时候触发
    __call__(self):实例像函数一样被调用时触发
    

    代码示例:

    class Person(object):
        def __new__(cls, name, age, city="beijing"):
            print('__new__()方法,"创建实例"时触发。')
            instance = super(Person, cls).__new__(cls)
            # instance = object.__new__()
            print(instance, id(instance))
            return instance
    
        def __init__(self, name, age, city="beijing"):
            print('__init__()方法,"初始化实例"时触发。')
            # __init__()的输入参数self,就是__new__()的返回值instance
            print(self, id(self))
            self.name = name
            self.age = age
            self.city = city
    
        # 普通方法
        def cook(self, menu):
            print('这是一个普通函数:cook()')
            print(f"{self.name}正在煮{menu}...")
    
        def __call__(self, course):
            print('__call__()方法,"实例像函数一样被调用"时触发。')
            print(f"{self.name}正在自习室学习{course}...")
    
        def __del__(self):
            print('__del__()方法,"实例销毁"时触发。')
    
    
    # 先触发__new__()创建一个instance,然后自动调用__init__()对实例进行初始化
    p = Person('Tom', 16, city='shanghai')
    print("----------")
    p.cook('coffee')  # 调用普通函数
    print("----------")
    p('Maths')  # 允许实例像函数一样被调用,触发__call__()方法
    print("----------")
    del p  # 实例被销毁,触发__del__()方法
    

    运行结果:

    __new__()方法,"创建实例"时触发。
    <__main__.Person object at 0x104001c90> 4362083472
    __init__()方法,"初始化实例"时触发。
    <__main__.Person object at 0x104001c90> 4362083472
    ----------
    这是一个普通函数:cook()
    Tom正在煮coffee...
    ----------
    __call__()方法,"实例像函数一样被调用"时触发。
    Tom正在自习室学习Maths...
    ----------
    __del__()方法,"实例销毁"时触发。
    
    2.实例的比较
    __eq__(self, other):定义相等符号的行为,==
    __ne__(self, other):定义不等符号的行为,!=
    __lt__(self, other):定义小于符号的行为,<
    __gt__(self, other):定义大于符号的行为,>
    __le__(self, other):定义小于等于符号的行为,<=
    __ge__(self, other):定义大于等于符号的行为,>=
    

    代码示例:

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __eq__(self, other):
            print('实例比较"=="时触发__eq__()')
            return self.age == other.age
    
        def __ne__(self, other):
            print('实例比较"!="时触发__ne__()')
            return self.age != other.age
    
        def __gt__(self, other):
            print('实例比较">"时触发__gt__()')
            return self.age > other.age
    
        def __lt__(self, other):
            print('实例比较"<"时触发__lt__()')
            return self.age < other.age
    
        def __ge__(self, other):
            print('实例比较"<="时触发__ge__()')
            return self.age >= other.age
    
        def __le__(self, other):
            print('实例比较"<="时触发__le__()')
            return self.age <= other.age
    
    
    p1, p2 = Person('Tom', 16), Person("Json", 16)
    print(p1 == p2)  # 触发__eq__()
    print("----------")
    print(p1 != p2)  # 触发__ne__()
    print("----------")
    print(p1 > p2)  # 触发__gt__()
    print("----------")
    print(p1 < p2)  # 触发__lt__()
    print("----------")
    print(p1 >= p2)  # 触发__ge__()
    print("----------")
    print(p1 <= p2)  # 触发__le__()
    

    运行结果:

    实例比较"=="时触发__eq__()
    True
    ----------
    实例比较"!="时触发__ne__()
    False
    ----------
    实例比较">"时触发__gt__()
    False
    ----------
    实例比较"<"时触发__lt__()
    False
    ----------
    实例比较"<="时触发__ge__()
    True
    ----------
    实例比较"<="时触发__le__()
    True
    
    3.容器相关
    __len__(self):len(instance)时触发
    __getitem__(self, key):instance[key]时触发
    __setitem__(self, key, value):instance[key]=value时触发
    __delitem__(self, key, value):del instance[key]时触发
    

    代码示例:

    class Book(object):
        def __init__(self, title, page_size=100):
            self.title = title
            self.page_size = page_size
            self.li = [10, 20, 30]
    
        def __len__(self):
            print('调用"len(instance)"时触发__len__()方法')
            return self.page_size
    
        def __getitem__(self, item):
            print('"调用instance[key]"时触发__getitem__()方法')
            return self.li[item]
    
        def __setitem__(self, key, value):
            print('"调用instance[key]=value"时触发__setitem__()方法')
            self.li[key] = value
    
        def __delitem__(self, key):
            print('"调用del instance[key]"时触发__delitem__()方法')
            del self.li[key]
    
    
    book = Book('maths', page_size=288)
    print("这本书的页数:", len(book))  # 触发__len__()方法
    print("----------")
    print(book[0])  # 触发__getitem__()
    print("----------")
    print("before book.li:", book.li)
    book[0] = 8  # 触发__setitem__()方法
    print("middle book.li:", book.li)
    print("----------")
    del book[0]  # 触发__delitem__()
    print("finally book.li:", book.li)
    

    运行结果:

    调用"len(instance)"时触发__len__()方法
    这本书的页数: 288
    ----------
    "调用instance[key]"时触发__getitem__()方法
    10
    ----------
    before book.li: [10, 20, 30]
    "调用instance[key]=value"时触发__setitem__()方法
    middle book.li: [8, 20, 30]
    ----------
    "调用del instance[key]"时触发__delitem__()方法
    finally book.li: [20, 30]
    
    4.迭代器
    定义一个迭代器,需实现__iter__()和__next__()。
    __iter__(self):调用iter(instance)时触发,返回一个迭代器
    __next__(self):调用next(instance)时或对instance进行迭代时触发
    

    代码示例:

    # 自定义迭代器
    class MyIter(object):
        def __init__(self, total, start=0):
            self.total = total
            self.start = start
    
        def __iter__(self):
            print('"调用iter(instance)"时触发__iter__()')
            return self
    
        def __next__(self):
            print('"调用next(instance)"时触发__next__()')
            if self.start < self.total:
                self.start += 1
                return self.start
            else:
                raise StopIteration
    
    
    myIter = MyIter(5)
    print(next(myIter))  # 触发__next__()
    print("----------")
    it = iter(myIter)  # 触发__iter__()
    print("----------")
    print(next(it))  # 触发__next__()
    print("----------")
    for value in it:  # 进行迭代操作,触发__next__()
        print(value)
    

    运行结果:

    "调用next(instance)"时触发__next__()
    1
    ----------
    "调用iter(instance)"时触发__iter__()
    ----------
    "调用next(instance)"时触发__next__()
    2
    ----------
    "调用iter(instance)"时触发__iter__()
    "调用next(instance)"时触发__next__()
    3
    "调用next(instance)"时触发__next__()
    4
    "调用next(instance)"时触发__next__()
    5
    "调用next(instance)"时触发__next__()
    

    相关文章

      网友评论

        本文标题:Python 魔术方法

        本文链接:https://www.haomeiwen.com/subject/zzdttltx.html