• 面对对象之类的内置方法


    TOC

    在总结内置函数之前的一段和sean老师的聊天记录,希望可以帮助你理解下面的知识点:

    类的内置方法(魔法方法)

    凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,也称之为魔法方法

    • 类的内置方法,会在某种条件满足下自动触发

    __new__()

    __init__()触发前,自动触发。调用该类的时,内部会通过__new__()产生一个新对象。

    class Demo:  # 在python3中所有的类默认继承object
        def __init__(self):
            print('此处是__init__方法的执行')
    
        def __new__(cls, *args, **kwargs):
            print('此处是__new__方法的执行')
    
    
    Demo()
    
    >>> 此处是__new__()方法的执行

    我们发现此处虽然执行了__new__(),但并未执行__init__()的方法,让我们点进源码中看一下:

    python3中所有的类默认继承object,点object进去可以看到

    源码中介绍此方法会创建并返回一个新的对象,我们再看我们写的代码:

        这里相当于我们对Demo默认继承的父类object进行了`方法重写`,此时也是多态的一种表现形式,子类继承父类object,对object中的`__new__()`进行了方法重写,因此会执行子类Demo的`__new__()`方法。(在子类中找到该方法时,就不会再往父类中查找该方法。)
    
        当我们没有对object中的方法重写时,object会自动执行它内部的`__new__()`并调用`__init__()`,但是方法重写后,执行的是Demo中的`__new__()`,因此并不会自动帮我们调用`__init__()`。(我们Demo类中并没有写相关调用`__init__()`的方法。)
    

    其实object也是python自定义的一个类:

        解决方案:在末尾的return中,我们重新调用父类object中的`__new__`的方法:
    

    此时父类中执行__new__()后自动帮我们调用__init__()所以此时可以打印出来__init__的信息。

    __init__()

    在类调用的时候触发,通过产生的对象自动调用__init__()

    注意:优先级没有__new__的高

    __setattr__()

    object.属性 = values,添加或修改属性时触发

    class Demo:
        def __init__(self):
            print('此处是__init__方法的执行')
    
        def __setattr__(self, key, value):
            print('此处是__setattr__方法的执行')
            print(key, value)
    
    
    obj = Demo()
    obj.x = 10

    我们尝试打印一下看有没有添加上这个x的属性:

    此时,虽然我们给obj对象添加了一个x的属性,但由于我们还是跟刚开始我和sean老师聊天中讲的一样,我们在类内部重写了默认继承的object的__setattr__()的方法,因此不会去执行父类中的__setattr__()的方法,因为默认查找的顺序是当前对象到当前子类,再到父类。我们也没在子类Demo中__setattr__()方法里进行复制操作,因此并没有将值新增上去。

    如果我们不在Demo中自己重写父类中的方法,就可以继承父类中的方法,因此我们直接,obj.x = 10就可以将属性添加上了,效果如下:(这是python内置的类中帮我们做的)

    那怎么解决这个问题呢?我们可以重写父类的方法后,对对象的字典进行赋值操作,如下:

    为什么可以对对象的字典进行赋值?我们可以打印一下对象的属性字典中的内容:

    不可以在方法内,利用self.key = value进行赋值,这样会重复调用__setattr__()进入死循环。(因为只要检测到对象.属性 = 值的时候就会触发__setattr__()

    我们也可以看一下类的字典:

    __getattr__()

    对象.属性获取属性时,若属性没有时触发。

    返回是None,因此我们可以在方法中给他一个返回值:

    __getattribute__()

    注意: 只要__getattr__ 与 getattribute 同时存在类的内部,只会触发__getattribute__。

    在“对象.属性”获取属性时,若"属性没有"时触发。

    __call__()

    在调用对象对象 + ()时触发

    __str__()

    在打印对象时触发

    • 该方法必须要有一个“字符串”返回值

    __getitem__()

    在对象通过”对象[key]获取属性时触发

    __setitem__()

    在对象通过对象[key] = value设置属性时触发





  • 相关阅读:
    《安富莱嵌入式周报》第217期:2021.06.14--2021.06.20
    【STM32H7】第27章 ThreadX GUIX数字小键盘的实现
    【STM32H7】第26章 ThreadX GUIX波形控件Line Chart
    【STM32F429】第25章 ThreadX GUIX数字小键盘的实现
    【STM32F429】第24章 ThreadX GUIX波形控件Line Chart
    MongoDB索引和用户基础
    MongoDB基本操作
    Redis高并发问题
    Redis客户端和数据的一致性
    Redis分布式方案
  • 原文地址:https://www.cnblogs.com/cnhyk/p/11958871.html
Copyright © 2020-2023  润新知