跳转至

类和对象-魔法方法

__init__方法

在对象初始化的时候实现个性化定制,在类实例化的时候自动进行调用。

语法: __init__(self[, ..])

__new__ 方法

__init__方法调用前被调用,对象是由该方法进行创建,实例化对象调用的第一个方法就是该方法。

语法: __new__(cls[, ..])

一般在类的继承中,继承的是不可变类型的类,使用 __new__ 方法,可以对不可变的类进行继承修改,另一个是在元类中定制类。

Python
# 定义类,继承str类,并使用new方法可以将不可变对象进行修改,比如以下进行从写str类,默认将字符串都变成大写
class Capstr(str):
    # 在继承str之前使用new方法在str类创建对象之前进行自定义,然后再执行str的new方法
    def __new__(cls, string):
        string = string.upper()
        return super().__new__(cls, string)

# 定义对象
test = Capstr("aBc")
# 可以发现默认都将字符串进行大写
print(test)  # ABC
# 同样可以继续使用str对应的方法,将字符串变为小写
print(test.lower())  # abc

__del__方法

在对象即将被销毁的时候执行方法的内容。

语法: __del__(self)

注意: 并不是删除销毁对象都会执行 __del__ 方法,只有检测到该对象没有任何引用的时候才会将它销毁,然后再执行 __del__方法。

Python
# 创建类C,并定义del方法
class C:
    def __init__(self):
        print("对象创建成功~")

    def __del__(self):
        print("对象销毁成功~")

# 创建对象执行init方法
c = C()  # 对象创建成功~
# 对象销毁执行del方法
del c        # 对象销毁成功~

# 如果创建的对象存在其他变量的引用,则不会执行del语句
a = C()
s = a
del a
print(12345)
# 执行顺序
# 对象创建成功~
# 123456
# # 对象销毁成功~

通过 __del__方法将函数销毁前传递出去

Python
# 方法一,通过全局变量的方式进行传递(不推荐)
class A:
    def __init__(self, name):
        self.name = name

    def __del__(self):
        # 创建全局变量x,将self值传递给x
        global x
        x = self

a = A(123)
del a
print(x.name)

# 方法二,通过函数进行传递(闭包函数)
# 创建类A,定义__del__方法,将函数进行传递
class A:
    def __init__(self, name, func):
        self.name = name
        self.func = func

    def __del__(self):
        self.func(self)

# 通过闭包函数进行值的传递,当调用闭包函数a的时候,传入了函数self参数,此时修改了函数外部变量x等于self,就将self传递出来,当不适用参数调用闭包函数则执行的是return x,此时就把self函数调用了
def a():
    x = 0

    def b(y=None):
        nonlocal x
        if y:
            x = y
        else:
            return x
    return b

# 将闭包函数外部函数赋值给c
c = a()
# 通过创建对象,将c函数传递给类
e = A(123, c)
print(e)  # <__main__.A object at 0x101031fa0>
# 删除对象e,此时将执行__del__方法,实际执行的是闭包函数内部函数,然后将值进行返回c
del e
# 将c赋值给变量g,此时,g就是类对象的self
g = c()
print(g)  # <__main__.A object at 0x101031fa0>
print(g.name)  # 123

属性访问相关魔法方法

hasattr 函数

判断某个属性是否存在。

Python
1
2
3
4
5
6
7
8
9
# 定义类
class Test:
    def __init__(self, name, age):
        self.name = name
        self._age = age

test = Test("aa", 18)
print(hasattr(test, "name"))                # True
print(hasattr(test, "_Test__age"))  # True

getattr 函数魔法方法 __getattribute____getattr__

getattr: 获取某个属性。

__getattribute__ 魔法方法: 当访问对象的属性,会被该方法拦截,执行该方法内容。

__getattr__魔法方法: 当访问对象的属性不存在,会先执行 __getattribute__ 魔法方法,然后执行 __getattr__魔法方法。

Python
# getattr函数
# 定义类
class Test:
    def __init__(self, name, age):
        self.name = name
        self._age = age

test = Test("aa", 18)
print(getattr(test, "name"))                        # aa
print(getattr(test, "_Test__age"))          # 18


# 对应魔法方法
class Test:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    # 当使用函数getattr则会调用该魔法方法
    def __getattribute__(self, item):
        print("被__getattribute__拦截")
        return super().__getattribute__(item)

    # 当使用函数getattr查询不存在对象属性这回执行该魔法方法
    def __getattr__(self, item):
        if item == "111":
            print(111)
        else:
            print("没有该元素")


test = Test("aaa", 18)
print(getattr(test, "name"))
# 被__getattribute__拦截
# aaa
getattr(test, "111")
# 被__getattribute__拦截
# 111
getattr(test, "222")
# 被__getattribute__拦截
# 没有该元素

setattr 函数魔法方法 __setattr__

设置某个属性。

Python
# setattr函数
# 定义类
class Test:
    def __init__(self, name, age):
        self.name = name
        self._age = age

test = Test("aa", 18)
setattr(test, "name", "bb")
setattr(test, "_Test__age", 19)
print(getattr(test, "name"))                    # bb
print(getattr(test, "_Test__age"))      # 19

# 对应魔法方法
class Test:
    def __setattr__(self, name, value):
        self.__dict__[name] = value


test = Test()
test.name = "aa"
print(test.name)            # aa

delattr 函数

删除某个属性。

Python
# delattr函数
# 定义类
class Test:
    def __init__(self, name, age):
        self.name = name
        self._age = age

test = Test("aa", 18)
delattr(test, "name")
print(hasattr(test, "name"))            # False

# 对应魔法方法
class Test:
    def __setattr__(self, key, value):
        self.__dict__[key] = value

    def __delattr__(self, item):
        self.__dict__.pop(item)


test = Test()
test.name = "aa"
print(test.__dict__)            # {'name': 'aa'}
del test.name
print(test.__dict__)            # {}