Python常用魔术方法总结

2019-08-02  本文已影响0人  慢慢慢慢热

__init__:构造函数

class Human:

    def __init__(self, name):
        print('init method for {}'.format(name))

    # 方法
    def eat(self):
        print('eat method')

    def run(self):
        print('run method')


human = Human('chengjie')  # 执行这一步实例化对象human之后, 会触发 __init__, 打印出init method for chengjie

__new__:构造函数

class Human:

    def __init__(self, name):
        print('init method for {}'.format(name))

    def __new__(cls, name):
        print(name)
        if name == 'chengjie':
            r = super(Human, cls).__new__(cls)
            return r
        else:
            pass


    # 方法
    def eat(self):
        print('eat method')

    def run(self):
        print('run method')


human = Human('chengjie')  # 执行这一步实例化对象human之后, 会先触发__new__打印出chengjie,返回实例化对象,再触发 __init__,打印出init method for chengjie

__del__:析构方法

class Human:

    def __init__(self, name):
        print('init method for {}'.format(name))

    def __new__(cls, name):
        print(name)
        if name == 'chengjie':
            r = super(Human, cls).__new__(cls)
            return r
        else:
            pass

    def __del__(self):
        print('del method')


    # 方法
    def eat(self):
        print('eat method')

    def run(self):
        print('run method')


human = Human('chengjie')  # 执行这一步实例化对象human之后, 会先触发__new__打印出chengjie,返回实例化对象,再触发 __init__,打印出init method for chengjie
human2 = human
del human # 此时不会触发__del__,在程序最后才会触发,如果没有human2 = human,则在此处调用del会触发__del__,程序最后则不会触发
print('running') # 在执行完这一句之后,会触发__del__,打印出del method,__del__总是会在程序最后被触发

__call__

class MakeCake:

    def buy_yuan_liao(self):
        print('购买原料')

    def huo_mian(self):
        print('和面')

    def fa_jiao(self):
        print('发酵')

    def hong_bei(self):
        print('烘焙')

    def __call__(self, *args, **kwargs):
        self.buy_yuan_liao()
        self.huo_mian()
        self.fa_jiao()
        self.hong_bei()
        print('蛋糕制作完成')


maek_cake = MakeCake() # 实例化一个类MakeCake的对象make_cake
maek_cake() # 把对象make_cake当做一个函数调用
>>>>购买原料
    和面
    发酵
    烘焙
    蛋糕制作完成

__len__

class Human:

    def __init__(self, name):
        self.name = name

    def __len__(self):
        # 必须有返回值,而且必须是整形
        return len(self.name)


    # 方法
    def eat(self):
        print('eat method')

    def run(self):
        print('run method')


human = Human('chengjie')
print(len(human)) #如果没有实现__len__, 则无法直接使用len(human), 否则报TypeError: object of type 'Human' has no len(), 实现了__len__后,可以根据需要

>>>>8

__str__

class Human:

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return 'Name: %s' % self.name

    # 方法
    def eat(self):
        print('eat method')

    def run(self):
        print('run method')


human = Human('Python')
print(human)   #如果没有__str__魔术方法,则打印出来的是类似于<__main__.Human object at 0x000001BFE3F39828>,这是继承自object的__str__方法

>>>>>Name: Python

__repr__

class Human:

    def __init__(self, name):
        self.name = name

    # def __str__(self):
    #     return 'Name: %s' % self.name

    def __repr__(self):
        return 'Name:%s' % self.name

    # 方法
    def eat(self):
        print('eat method')

    def run(self):
        print('run method')


human = Human('Python')
print(human) # 该类没有实现__str__,但是打印对象的时候,会执行__repr__

>>>>>Name:Python

__bool__

class Human:

    def __init__(self, name):
        self.name = name

    def __bool__(self):
        if self.name == 'cheng':
            return True
        else:
            return False

    # 方法
    def eat(self):
        print('eat method')

    def run(self):
        print('run method')


human = Human('cheng')
human2 = Human('Python')
print(bool(human))
print(bool(human2))

>>>>>True
>>>>>False

与属性相关的魔术方法

属性的访问顺序

  1. 调用__getattribute__
  2. 调用数据描述符
  3. 调用当前对象的所属成员
  4. 调用类的所属成员
  5. 调用非数据描述符
  6. 调用父类的所属成员
  7. 调用__getattr__

__getattribute__

class Human:

    def __init__(self):
        self.name = 'Python'
        self.sex = 'male'
        self.age = 18

    def __getattribute__(self, item):
        print('getattribute call by %s' % self)
        # return self.name   如果返回的是self.name,则会报错
        return super().__getattribute__(item)

    def eat(self):
        print('eat method is running')


human = Human()
print(human.name)

>>>>>>>>getattribute call by <__main__.Human object at 0x000001D633849240>
>>>>>>>>Python

__getattr__

class Human:

    # 成员属性
    def __init__(self):
        self.name = 'Python'
        self.sex = 'male'
        self.age = 18

    def __getattr__(self, item):
        if item == 'score':
            return 88
        else:
            return 'error item'

    def eat(self):
        print('eat method is running')


human = Human()
print(human.score)
print(human.school)

>>>>88
>>>>error item

__setattr__

class Human:

    # 成员属性
    def __init__(self):
        self.name = 'Python'
        self.sex = 'male'
        self.age = 18

    def __setattr__(self, key, value):
        if key == 'school':   # 当设置的成员名称为school时,直接跳过,不设置
            pass
        else:
            super().__setattr__(key,value) #注意此处不可以用self.key = value

    def eat(self):
        print('eat method is running')


human = Human()
human.school = 'QH'
human.score = 99
print(human.school)  # 报错,school不存在
print(human.score) # 输出 99

>>>>AttributeError: 'Human' object has no attribute 'school'
>>>>99

__delattr__

class Human:

    def __init__(self):
        self.name = 'Python'
        self.sex = 'male'
        self.age = 18

    def __delattr__(self, item):
        if item == 'name': # 当删除的对象成员名称为name时,不执行删除操作,即限制了删除name成员
            pass
        else:
            # del self.sex  如果执行此行,则会报错,递归数过大
            return super().__delattr__(item)

    def eat(self):
        print('eat method is running')


human = Human()
del human.name  # 不会删除name属性
del human.sex  # 会删除sex属性
print(human.name)
print(human.sex)

>>>>Python
>>>>AttributeError: 'Human' object has no attribute 'sex'
上一篇下一篇

猜你喜欢

热点阅读