Python 面向对象之魔法方法

Python 面向对象之魔法方法

【一】魔法方法

  • python给类和对象提供了大量的内置方法,这些内置方法也称为魔法方法
  • 其名称以双下划线开头和结尾,这些方法在类中有特殊的含义,用于实现对象的特定行为
  • 这些魔法方法总是在某种条件下自动触发执行,就像魔法一样

【1】__new____init____call____del__

  • new:创建对象实例
    • 参数包括类本身(cls),以及实例化时传递的其他参数
    • 返回一个新创建的对象实例
  • init:负责对象的初始化工作
    • 参数包括实例对象(self),以及实例化传递的其他参数
    • 默认不返回值
  • call:对象被调用时执行的方法
    • 参数包括实例对象(self)和调用时传递的参数
    • 默认不返回值
  • del:对象被销毁(垃圾回收)时自动调用
    • 参数只有实例对象(self)
    • 没有返回值
  • 执行顺序:new–>init–>实例操作(实例调用)–>del
class A:
    def __call__(self, *args, **kwargs):
        print("run call")
    def __new__(cls, *args, **kwargs):
        print("run new")
        return super().__new__(cls, *args, **kwargs)
    def __init__(self):
        print("run init")
    def __del__(self):
        print("run del")

a = A()
a()
print("a do somthing")
a()
# run new
# run init
# run call
# a do somthing
# run call
# run del

【2】__str____repr__

  • repr:产生一个字符串,可以通过eval函数重新得到该对象
  • str:产生一个字符串,方便阅读
  • __doc__:不是魔法方法,是一个属性,普通函数也有,返回注释内容
class A:
    '''
    类的注释内容
    '''
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __repr__(self):
        return f"A({self.x}, {self.y})"
    def __str__(self):
        return f"获取x和y"

def func():
    """
    func注释内瓤
    :return:
    """

a = A(12,13)
print(repr(a)) # print(a.__repr__())
print(str(a))  # print(a.__str__())
# A(12, 13)
# 获取x和y

print(a.__doc__)
print(func.__doc__)
#     类的注释内容
#     func注释内瓤
#     :return:

【3】__enter____exit__

  • 上下文管理器是一种实现了这两个特殊方法的对象
  • 这种对象可以使用with语句执行管理,确保资源正确获取和释放
  • enter:进入上下文时操作,如资源、设置环境等
    • 只能有一个参数self
    • 通常返回一个与上下文相关的对象,可以在with语句中使用
  • exit:离开上下文执行的操作,如释放资源、清理环境等
    • self, exc_type, exc_val, exc_tb
    • self:实例对象
    • exc_type:上下文中代码块发生的异常类型,如果没有就是None
    • exc_val:异常值,没有就是None
    • exc_tb:异常的追追踪信息对象,没有则为None
    • 返回布尔值,表示是否要压制异常。
      • True,压制异常,程序继续运行
      • FalseNone,异常将被传播,程序会中断
class Open:
    def __enter__(self):
        print("enter")
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit")
        if exc_type is not None:
            print(f"exception type:{exc_type}")
            print(f"exception value:{exc_val}")
        return False

with Open() as my_fp:
    print("run my_fp")
# enter
# run my_fp
# exit

【4】__setattr____getattr____delattr____getattribute__

  • 对实例对象的属性进行操作处理方法
  • 通过实例.属性触发
  • 注意
    • 错误操作将存在循环引用的问题
    • getattr只有属性不存在时才会触发
class A:
    def __getattr__(self, item):
        return f"{item}不存在"
    def __setattr__(self, key, value):
        # self.key = value # 将会导致循环引用
        self.__dict__[key] = value
    def __delattr__(self, item):
        # del self.item # 将会导致循环引用
        del self.__dict__[item]

a = A()
a.name = "bruce"
print(a.name) # bruce
print(a.age) # age不存在
del a.name
  • 只要有.操作都会执行getattribute
  • 不存在直接报错,但是有getattr的时候会再次进入getatter,不会报错
class A:

    def __setattr__(self, key, value):
        # self.key = value # 将会导致循环引用
        self.__dict__[key] = value
    def __delattr__(self, item):
        # del self.item # 将会导致循环引用
        del self.__dict__[item]
    def __getattr__(self, item):
        return f"{item}不存在"

    def __getattribute__(self, item):
        print("全部捕获")
        return super().__getattribute__(item)

a = A()
a.name = "bruce"
print(a.name)
print(a.age)
del a.name
# 全部捕获
# 全部捕获
# bruce
# 全部捕获
# age不存在
# 全部捕获

【5】__setitem____getitem____delitem__

  • 将对象向字典一样处理
  • getitem:通过索引操作符号[]获取对象元素时调用
  • setitem:通过索引操作符号[]设置对象元素时调用
  • delitem:通过索引操作符号[]删除对象元素时调用
class MyDict:
    def __init__(self):
        self.data_dict = dict()

    def __getitem__(self, item):
        return self.data_dict[item]
    def __setitem__(self, key, value):
        self.data_dict[key] = value
    def __delitem__(self, key):
        del self.data_dict[key]

a = MyDict()
a["name"] = "bruce"
print(a['name'])
del a["name"]
print(a["name"])  # 被删除

【6】关系运算符系列

  • gt(greater than)大于

  • lt(lower than)小于

  • eq(equal)

  • ne(not equal)

  • ge(greater than or equal)

  • le(lower than or equal)

  • 还有其他运算符号等等

class MyMoney:
    def __init__(self, money: float):
        self.money = money

    def __gt__(self, other):
        return self.money > other.money
    def __lt__(self, other):
        return self.money < other.money
    def __eq__(self, other):
        return self.money == other.money
    def __ne__(self, other):
        return self.money != other.money
    def __ge__(self, other):
        return self.money >= other.money
    def __le__(self, other):
        return self.money <= other.money


money1 = MyMoney(19.9)
money2 = MyMoney(20)
print(money1 < money2) # True
print(money1 == money2) # False
print(money1 <= money2) # True
print(money1 > money2) # False
print(money1 >= money2) # False
print(money1 != money2) # True

【7】__iter____next__

  • 创建可迭代对象

  • iter:返回一个可迭代对象

  • next:迭代返回下一个值

# 斐波那契数列
class Fibonacci:
    def __init__(self, end: int):
        self.a, self.b = 0, 1
        self.end = end
        self.start = 0

    def __iter__(self):
        return self

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b
        self.start += 1
        if self.start > self.end:
            raise StopIteration()
        return self.a

for i in Fibonacci(5):
    print(i)
# 1
# 1
# 2
# 3
# 5    

【8】描述符__get____set____delete__

  • 描述符是哟中通过实现特定协议的类,使得类的属性访问具有可控的行为

  • 描述符主要用于管理属性的访问、修改和删除操作

  • 描述符本质是一个新类,这个类中至少要实现一个,这也被称为描述符协议

class Descriptor:
    def __get__(self, instance, owner):
        """
        :param instance: 实例对象
        :param owner: 拥有者类
        :return: 值
        """
        print("will get value")
        return instance._value
    def __set__(self, instance, value):
        """
        :param instance: 实例对象
        :param value: 值
        :return: None
        """
        print("will set value")
        instance._value = value

    def __delete__(self, instance):
        """
        :param instance: 实例对象
        :return: None
        """
        print("will delete value")
        del instance._value

class Myclass:
    def __init__(self, value):
        self._value = value
    descriptor = Descriptor()

instance = Myclass("bruce")
instance.descriptor = 100
print(instance.descriptor)
del instance.descriptor
# print(instance.descriptor) # 删除
# will set value
# will get value
# 100
# will delete value

【四】总结

Python 面向对象之魔法方法_第1张图片

你可能感兴趣的:(Python,面向对象,python,开发语言)