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


    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设置属性时触发





  • 相关阅读:
    江西财经大学第一届程序设计竞赛 F题 -解方程
    HDU2553 N皇后问题
    2018年长沙理工大学第十三届程序设计竞赛 G 题:逃离迷宫
    Codeforces #475 div2
    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 L题 K序列
    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 I题 二数
    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 F题 1+2=3 ?
    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 Wasserstein Distance
    hdu 5685
    hdu 5512 Pagodas
  • 原文地址:https://www.cnblogs.com/cnhyk/p/11958871.html
Copyright © 2020-2023  润新知