Python 魔术方法解析二

265 阅读4分钟

image.png

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战

前言

众所周知,Python是面向对象编程的高级语言。创建类过程中,我们可以重写以双下划线"__"开头结尾的魔法方法,来实现个性化程序。

目前我们已经对Python 魔法方法学习了一部分比如以下方法:

  • __init__():初始化实例对象的构造函数
  • __del__(): 销毁对象的析构函数
  • __enter__()__exit__():实现with上下文管理器访问文件内容操作
  • __getattr__()__setattr__():使用对象属性方法,可以对对象属性进行访问

在Python 魔法方法还支持操作符计算、单双目计算的魔法方法,我们都可以进行重写个性化定制方法。

与此同时,我们在 Python 还可以支持自定义序列,使用 __len__()和- __getitem__() 两个方法就可以实现自定义不可变序列,如果要实现可变序列还需要 __setitem____delitem__实现可变序列可更改、删除元素操作。

Python 魔法方法除了上述方法外,它还有其他的方法如反射、复制、对象描述魔法方法。

本期,我们将继续学习python 剩余的魔术方法,Let's go~

1. 可调用对象

Python 中有一个具有强大的方法的__call__(self)方法,可以支持类实例可以像函数方法一样,通过"对象名()"方式进行调用。

  • __call__(self): 允许一个类的实例像函数一样被调用。
  • 对象名() 等同于 对象名.__call__().
  • __call__(self)方法参数是可变,可以定义包含多个参数的方法
class Stundent:

    def __call__(self, name,age):

        print("name:{0},age:{1}".format(name,age))


stu = Stundent()

stu("Tom",12)
stu.__call__("Tom",12)
  • __call__(self)方法常用在对象状态改变的优雅做法
class Stundent:

    def __init__(self,name,age,sex):

        self.name = name
        self.age = age
        self.sex = sex

    def __call__(self, name,age):

        print("name:{0},age:{1}".format(name,age))


stu = Stundent("Tom",20,"Bpy")

stu("Tom",12)
  • __call__(self) 填补 hasattr()方法的不足

hasattr()方法用于查找类的实体对象中是否包含指定名称的属性或者方法。但该函数有一个缺陷是无法判断指定查询的名称是否类属性还是方法。

我们可以使用如下形式进行判断查询:

print(hasattr(stu.name,"__call__"))

2. 复制操作方法

我们在之前对Python 序列如list、set、tuple等学习过程中,或多或少都对其进行切片索引操作。这些操作往往会涉及复制的概念。

序列又分为可变序列和不可变序列,我们对序列进行拷贝,会调用两种魔法方法

  • 浅拷贝:__copy__(self)
  • 深拷贝:__deepcopy__(self)

我们在对可变序列对象进行复制操作时,如果我们期望不对原有数据产生影响,这时候我们可以调用__copy__(self)方法。

  • __call__(self)方法:是当类的实例调用copy.copy()方法时所产生的行为
  • __call__(self)方法,是执行浅拷贝动作,拷贝的对象后,其所有的数据都会被引用。
  • 对于浅拷贝中的数据的更改,仍然会可能导致原始对象的改变

当我们对序列进行深拷贝时,python 解释器会调用魔法方法__deepcopy__(self)

  • __deepcopy__(self,memodict={})方法:是类实例对象调用copy.deepcopy()所产生的行为
  • __deepcopy__(self,memodict={})方法,是执行深拷贝,对象和其数据都进行拷贝。
  • memodict 是对之前的拷贝对象进行缓存,对其在拷贝过程中对递归拷贝时无限递归。

3. 检查类型

Python 中如果我们要查询类和子类的关系,要怎么进行呢?

Python 提供两个魔法方法,方便我们来进行类型检查。

  • __instancecheck__(self,instance)方法:检查一个实例是否是定义的类的实例
  • __subclasscheck__(self,subclass)方法:检查一个类是否是定义的类的子类

同时,Python 还为所有类提供一个base属性

  • __base__ :检查该类的所有直接父类,该属性返回所有直接父类组成的元组

4. 对象描述器

python 魔法方法提供了描述器,是可以通过获取、设置以及删除时访问类。

  • 描述器不是独立的,需要被所有者持有,并且存在其字典中
  • 当创建面向对象的数据库或者类,里面包含相互依赖的属性时,描述器将会非常有用的
  • 实现描述器时,一个类至少有__get__()__set__()__delete__()方法

__get__(self,instance,owner):定义描述器的值被取得时的行为。instance 是拥有该描述器对象的一个实例。owner 拥有者本身

__set__(self,instance,value): 定义描述器的值被改变时的行为。instance为描述器的一个实例,value要设置的值。

__delete__(self,instance):定义描述器的值被上传时的行为,instance为描述器的一个实例。

总结

本期,我们将Python 常用的魔法方法,进行了解和学习。在实际的工作中,我们要学以致用,多多练习。

以上是本期内容,欢迎大佬们点赞评论,下期见~~