2022年 11月 9日

Python 类的常用内置方法

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

凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,类的内置方法,会在满足某种条件下自动触发。

1.1__new__

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

class Demo(object):

    # 条件: __new__: 在__init__触发前,自动触发。
    def __new__(cls,*args,**kwargs):
        print('此处是__new__方法的执行')
        #python内部通过object调用的__new__实现产生一个空的对象 --->内存地址
        return object.__new__(cls,*args,**kwargs)

    #条件:__init__在调用类时自动触发
    def __init__(self):
        print('此处是__init__方法的执行')

Demo()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

1.2__getattr__

	__getattr__: 在通过 “对象.属性” 获取属性时,若 “属性没有” 时触发。
	
class Demo(object):
    # x =10

    def __getattr__(self,item):
        print('此处是__getattr__方法的执行')
        print(item)
        #return 想要返回的值
        return 123
obj1 = Demo()
print(obj1.x)

#执行结果:
此处是__getattr__方法的执行
x
123
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

1.3__getattribute__


条件: __getattribute__: 在通过 “对象.属性” 获取属性时,无论 "属性有没有" 都会触发执行。

class Demo:
    #x=10
    def __getattr__(self, item):
        print('此处是__getattr__方法的执行')

    def __getattribute__(self, item):
        print('此处是__getattribute__方法的执行')
        # 注意: 此处不能通过对象.属性,否则会产生递归调用,程序崩溃
        # return self.__dict__[item]
        print(item, '<-----打印属性名字')
        # raise AttributeError('抛出异常了')
obj1 = Demo()
obj1.x

# 注意: 只要__getattr__ 与 __getattribute__ 同时存在类的内部,只会触发__getattribute__。
#若 执行到__getattribute__ 发现raise AttributeError('抛出异常了'),则再触发__getattr__
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

1.4__setattr__与__delattr__

条件: __setattr__当 “对象.属性 = 属性值” , 添加或修改属性时触发执行。
条件:__delattr__当删除 “对象.属性” 属性的时候会触发执行。

class Demo:
    def __setattr__(self, key, value): # key---> 对象.属性名  value ---》 属性值
        print('此处是__setattr__方法的执行')
        print(key, value)
        # 出现递归
        # self.key = value
        # 此处是对 对象的名称空间 ---》 字典进行操作
        self.__dict__[key] = value
obj1 = Demo()
obj1.x =10
# 原来设置属性时,会自动触发父类中的__setattr__,内部为对象添加x属性,值为20
print(obj1.__dict__)

#执行结果:
此处是__setattr__方法的执行
x 10
{'x': 10}



class Demo:
    x = 1
    def __init__(self,y):
        self.y = y

    def __delattr__(self, item):
        print('此处是__delattr__方法的执行')

obj1 = Demo(10)
del obj1.y
del obj1.x

#执行结果:
此处是__delattr__方法的执行
此处是__delattr__方法的执行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

1.5__str__

引子:想一想下列情况为什么不一样?

l =list('hello')  #l是list类的实例化出来的一个实例,即一个对象
print(l)   #['h','e','l','l','o']

class Foo:
    pass
f1 = Foo()
print(f1)  #<__main__.Foo object at 0x0000022735920688>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

以上所知,所以python内部肯定有内化机制进行过处理,其实质原理如下

条件: __str__在打印对象时触发。

注意: 该方法必须要有一个 “字符串” 返回值。

class Demo:
    def __str__(self):
        print('此处是__str__方法的执行')
        return '自定制的对象的显示方式'  

obj1 =Demo()
print(obj1)

#执行结果:
此处是__str__方法的执行
自定制的对象的显示方式
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1.6__getitem__和__setitem__和__delitem__

条件:__getitem__在对象通过 “对象[key]” 获取属性时触发。

class Demo:
    def __init__(self,name):
        self.name=name
    def __getitem__(self, item):
        print('此处是__getitem__方法的执行')
        print(item)
        return self.__dict__[item]

obj1 = Demo('lili')
print(obj1, '<----- 打印的对象')
print(obj1['name'])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
条件:__setitem__在对象通过 “对象[key]=value值” 设置属性时触发。

class Demo:
    def __setitem__(self, key, value):
        print('此处是__setitem__方法的执行')
        self.__dict__[key] = value

obj1 = Demo()
print(obj1.__dict__)
obj1['name'] = 'baohan'
print(obj1.__dict__)

#执行结果:
{}
此处是__setitem__方法的执行
{'name': 'baohan'}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
条件:__delitem__在对象通过 del “对象[key]” 属性时触发。
class Demo:
    def __setitem__(self, key, value):
        print('此处是__setitem__方法的执行')
        self.__dict__[key] = value

    def __delitem__(self, key):
        print('此处是__delitem__方法的执行')
        self.__dict__.pop(key)

obj1 = Demo()
print(obj1.__dict__)
obj1['name'] = 'baohan'
print(obj1.__dict__)
#del obj1.name
del obj1['name']
print(obj1.__dict__)

#执行结果:
{}
此处是__setitem__方法的执行
{'name': 'baohan'}
此处是__delitem__方法的执行
{}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

1.7__call__

条件: __call__在调用对象 “对象 + ()” 时触发。

class Demo:
    def __call__(self, *args, **kwargs):
        print('此处是__call__方法的执行')
        # 调用对象时返回的值
        return [1,2,3,4]
obj1 =Demo()
obj1()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10