[Python进阶] 定制类:构建篇

这篇具有很好参考价值的文章主要介绍了[Python进阶] 定制类:构建篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

4.10.6 构建篇

4.10.6.1 init_subclass

init_subclass 是一个特殊的方法 (special method),在 Python 3.6 中被引入。它是在定义一个类的时候会自动调用的一个类方法,而不是实例方法。这个方法可以用来拦截子类的创建,并代替父类完成一些工作,比如添加类变量、检查属性并对其进行修改、注册子类等。
使用 init_subclass 方法可以让我们在子类继承父类时,自动完成一些默认的操作,使代码更加简洁、易读和可维护。
下面是一个简单的例子,演示了如何在父类中使用 init_subclass 方法来注册子类:

# 定义一个 Widget 父类
class Widget:
    # 定义一个空字典,用于存储子类
    registered_widgets = {}
    # 自动注册子类到 registered_widgets 字典中
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        Widget.registered_widgets[cls.__name__] = cls
# 定义两个子类 Button 和 Text ,继承自 Widget
class Button(Widget):
    pass
class Text(Widget):
    pass
# 在控制台输出注册的子类名
print(Widget.registered_widgets) # {'Button': <class '__main__.Button'>, 'Text': <class '__main__.Text'>}

这个例子中,我们定义了一个 Widget 父类,它有一个空的 registered_widgets 字典。当子类继承自 Widget 时,会调用 init_subclass 方法,将该子类的名称和类对象添加到 registered_widgets 中。最后,在控制台输出注册的子类名,可以看到 Button 和 Text 都被自动注册到了 Widget 的 registered_widgets 字典中。

4.10.6.2 set_name

__set_name__是一个特殊的Python内置方法,用于在attribute被设置为一个类的属性时被调用。主要用于描述符中,以便可以确定它们所属的类和它们的名称(attribute name)。
当一个属性被定义为一个类的属性时,如果有实现了__set_name__方法的描述符存在,Python会自动将其所属的类和该属性的名称作为参数调用此方法。因此,实现__set_name__方法的描述符可以保存这些参数并进行后续计算或验证等操作。
下面是一个简单的例子说明了__set_name__的应用:

class MyDescriptor:
    def __set_name__(self, owner, name):
        self.name = name
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(self.name)
    def __set__(self, instance, value):
        instance.__dict__[self.name] = value
class MyClass:
    x = MyDescriptor()
    def __init__(self, x):
        self.x = x

在上面的代码中,我们定义了一个名为MyDescriptor的自定义描述符,并实现了三个方法:set_nameget__和__set。__set_name__方法保存了该描述符所属的类和属性名称,并且在MyClass类定义时由Python自动调用执行。
随后,在MyClass的实例化对象初始化过程中,我们创建了一个名为x的对象并将其值设置为传入的参数x。由于MyDescriptor是作为x属性的描述符存在的,因此当该属性被赋值时,Python将自动调用其__set__方法,进而设置x属性的值。同时,在MyDescriptor的__get__方法中,我们获取了实例属性的值并返回了它。

4.10.6.3 class_getitem

__class_getitem__是Python中的一个特殊方法,用于在运行时为泛型类定义参数化类型。简单来说,它允许我们定义可以接受泛型参数的类。
在Python 3.7及以后版本中,它已经成为了PEP 560的一部分,并且可以作为泛型类型注释或类型变量标记等方面使用。
下面是一个简单的例子:

from typing import TypeVar, Generic
T = TypeVar('T')
class MyGenericClass(Generic[T]):
    def __init__(self, value: T):
        self.value = value
    def get_value(self) -> T:
        return self.value

在上面的示例中,我们定义了一个名为MyGenericClass的泛型类,其中使用[T]来指定参数化类型(也称为类型变量)。此外,我们实现了一个初始化方法和一个获取值的方法。
这个泛型类可以接受不同的类型参数进行实例化,例如:

str_instance = MyGenericClass[str]("Hello World")
int_instance = MyGenericClass[int](10)
print(str_instance.get_value()) # Output: 'Hello World'
print(int_instance.get_value()) # Output: 10

在这里,我们用[str]和[int]作为参数化类型来创建两个不同的实例。当类被实例化时,Python会调用__class_getitem__方法来获取参数化类型并将其应用于类。通过这种方式,我们能够创建一个适用于不同类型参数的泛型类。

4.10.6.4 mro_entries

mro_entries 是一个类属性,是 Python 中的 Method Resolution Order(MRO)算法的一部分。 MRO是确定多重继承中继承属性搜索顺序的算法。
在Python 3中,可以通过使用类属性__mro_entries__ 来控制计算得到方法解析次序元组(MRO tuple )中有哪些类被包含。
使用 mro_entries 可以灵活定制 MRO 元组。例如,在 MRO 计算时不考虑某个基类,或使用一个新的中间类等。
下面我们举一个简单的例子展示如何使用 mro_entries 控制方法解析次序元组:

class A:
    pass
class B(A):
    __mro_entries__ = (A,)  # 将A从B的方法解析次序元组中删除
class C(A):
    def foo(self):
        print("C.foo")
class D(B, C):
    pass
d = D()
d.foo()

输出将是 “C.foo” ,因为在D类的MRO tuple计算时,不包含B类而只包含了 A 类和 C 类。
注意:默认情况下,如果没有定义 mro_entries 属性,默认继承关系是按照宽度优先算法。 因此,我们可以使用 mro_entry 来修改默认的搜索顺序,以解决与默认搜索顺序相关的问题。

4.10.6.5 prepare

在Python中,__prepare__是一种特殊的方法,它可以用于自定义创建类的名称空间(类字典)。
在Python中,当我们定义一个类时,该类的名称空间将存储所有类属性和方法。通常,在类定义中使用dict()来创建这个名称空间。但是,我们可以通过实现 prepare 方法来自定义类的名称空间的创建过程。prepare() 方法必须返回一个映射对象,通常是一个字典,用于存储类成员。
下面是一个简单的示例,说明如何使用__prepare__方法:

class MyMeta(type):
    def __prepare__(name, bases):
        return {'foo': 42}
    
class MyClass(metaclass=MyMeta):
    pass
print(MyClass.foo) # 输出 42

在上述的示例中,我们定义了一个名为MyMeta的元类,并实现了__prepare__方法。 当我们使用这个元类来定义一个名为MyClass的类时,会自动调用MyMeta的 __prepare__方法。 实现的__prepare__方法返回了一个包含一个foo键和对应值的字典作为名称空间,在MyClass中定义了此变量。所以最终MyClass.foo返回42。
虽然这个例子很简单,但是自定义类字典有很多实际用途,例如:
记录每个类成员的定义顺序
检查名称和类型以确保符合特定规则
自动生成一些类成员等
总之,__prepare__方法可以使元类更加灵活,并提供更多自定义类行为的能力。

4.10.6.6 instancecheck、subclasscheck

在Python中,__instancecheck__是一个特殊方法,当使用内置的isinstance()函数检查对象类型时会自动调用。__instancecheck__的作用是控制isinstance()函数的行为,可以根据需要定制对于某个自定义类的实例是否满足某些条件。
下面是一个简单的例子:假设我们要创建一个自定义类 PositiveInteger,该类仅接受大于0的整数作为构造函数的输入,并且提供了一个方法来判断一个对象是否为正整数。

class PositiveInteger:
    def __init__(self, value):
        if not isinstance(value, int) or value <= 0:
            raise ValueError("PositiveInteger must be initialized with a positive integer")
        self.value = value
    
    def is_positive(self):
        return self.value > 0
    
    def __instancecheck__(self, instance):
        return isinstance(instance, int) and instance > 0

在这个类中,我们定义了__instancecheck__方法以定制isinstance()函数的行为。在上述实现中,如果需要检查的对象是一个大于0的整数,则返回True,否则返回False。这样,在使用isinstance()函数检查PositiveInteger类的实例时,就可以支持以下两种方式:

p = PositiveInteger(5)
print(isinstance(p, PositiveInteger)) # True
print(isinstance(10, PositiveInteger)) # True

第一次调用输出True是因为p是PositiveInteger类的实例,第二次输出True是因为10符合自定义类型PositiveInteger对象对应的条件,即一个大于0的整数。注意这里的重点是演示如何进行 instancecheck 方法的实现,关注点不在于 PositiveInteger 类本身的设计。
在Python中,__subclasscheck__是一种特殊方法(也称为魔术方法或Dunder method),用于自定义子类检查逻辑。
当使用issubclass(cls, class_or_tuple)函数时,Python会调用cls.subclasscheck(sub_cls)方法来确定sub_cls是否为cls的子类,如果__subclasscheck__方法返回True,则sub_cls是cls的子类,否则不是。
一个简单的例子如下:

class EvenNumbers:
    def __subclasscheck__(self, sub):
        return isinstance(sub, int) and sub % 2 == 0
class Four(EvenNumbers):
    pass
class Three:
    pass
print(issubclass(Four, EvenNumbers)) # True
print(issubclass(int, EvenNumbers)) # True
print(issubclass(Three, EvenNumbers)) # False

以上代码中,EvenNumbers类定义了一个__subclasscheck__方法,该方法定义了仅当子类是偶数时才被认为是子类。 Four类继承了EvenNumbers并且为偶数,所以Four是EvenNumbers的子类,而int是EvenNumbers的子类,因为它符合“是偶数”这一条件。 Three类既不是偶数也不是整数,因此不是EvenNumbers的子类。文章来源地址https://www.toymoban.com/news/detail-668685.html

到了这里,关于[Python进阶] 定制类:构建篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python进阶知识(一)

    最简单的模块化方式,你可以把函数、类、常量拆分到不同的文件,把它们放在同一个文 件夹,然后使用 from your_file import function_name, class_name 的方式调 用。之后,这些函数和类就可以在文件内直接使用了。 看看上面的示例代码,get_sum() 函数定义在 utils.py,Encoder 和 Decoder

    2024年02月10日
    浏览(34)
  • Python进阶知识(四)

    在Python中, concurrent.futures 模块提供了一种简单而强大的并发编程方式,称为\\\"Futures\\\"。它基于线程池( ThreadPoolExecutor )和进程池( ProcessPoolExecutor )的概念,使并发任务的管理和执行更加方便。 使用 concurrent.futures 模块,你可以将任务提交给执行器(Executor),然后通过 Fu

    2024年02月11日
    浏览(37)
  • Python进阶知识(三)

    在Python中,迭代器(Iterator)是一种用于遍历集合元素的对象。它是一个实现了迭代器协议(Iterator Protocol)的对象,该协议包含两个方法: __iter__ 和 __next__ 。 __iter__ 方法:返回迭代器对象自身。它在迭代开始之前被调用,用于初始化迭代器的状态。 __next__ 方法:返回迭代

    2024年02月10日
    浏览(39)
  • Python进阶知识(二)

    Python装饰器是一种用于修改函数或类的行为的特殊语法构造。装饰器允许在不修改原始代码的情况下,通过将函数或类包装在另一个函数中来添加额外的功能。 装饰器通常用于以下场景: 函数的日志记录:装饰器可以用来记录函数的调用信息,如函数名称、参数和返回值等

    2024年02月10日
    浏览(35)
  • 学习C++:C++进阶(六)如何在C++代码中调用python类,实例化python中类的对象,如何将conda中的深度学习环境导入C++项目中

    目录 1.应用场景 2.场景:利用maskrcnn深度学习网络实现语义分割 3.CMake配置python解释器

    2023年04月22日
    浏览(42)
  • Python小知识 - Python爬虫进阶:如何克服反爬虫技术

    Python爬虫进阶:如何克服反爬虫技术 爬虫是一种按照一定的规则,自动抓取网页信息的程序。爬虫也叫网页蜘蛛、蚂蚁、小水滴,是一种基于特定算法的自动化程序,能够按照一定的规则自动的抓取网页中的信息。爬虫程序的主要作用就是从一个网站或者一个网页中抓取所需

    2024年02月09日
    浏览(43)
  • Python基础知识进阶之数据爬虫

           爬虫是指利用网络抓取模块对某个网站或者某个应用中有价值的信息进行提取。还可以模拟用户在浏览器或者APP应用上的操作行为,实现程序自动化。简单来说就是我们把互联网有价值的信息都比喻成大的蜘蛛网,而各个节点就是存放的数据,而蜘蛛网的上蜘蛛比喻

    2024年02月09日
    浏览(61)
  • Python进阶知识:整理1 -> pySpark入门

    pySpark大数据分析过程分为3步: 数据输入、数据计算、数据输出 ,以下内容将重点介绍这三个过程   在数据输入完成后,都会得到一个 RDD类的对象 (RDD全称为弹性分布式数据集) map算子是将RDD的数据进行一条条处理(处理的逻辑基于map算子接收的处理函数),返回新的R

    2024年01月18日
    浏览(46)
  • 【python】16.Python语言进阶

    重要知识点 生成式(推导式)的用法 说明:生成式(推导式)可以用来生成列表、集合和字典。 嵌套的列表的坑 Python Tutor - VISUALIZE CODE AND GET LIVE HELP heapq 模块(堆排序) itertools 模块 collections 模块 常用的工具类: namedtuple :命令元组,它是一个类工厂,接受类型的名称和

    2024年01月17日
    浏览(35)
  • Python小知识 - 【Python】如何使用Pytorch构建机器学习模型

    【Python】如何使用Pytorch构建机器学习模型 机器学习是人工智能的一个分支,它的任务是在已有的数据集上学习,最终得到一个能够解决新问题的模型。Pytorch是一个开源的机器学习框架,它可以让我们用更少的代码构建模型,并且可以让模型训练的过程更加简单。 首先,我们

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包