Python编程思想(30):用 metaclass搞定一批类的特性

李宁老师已经在「极客起源」 微信公众号推出《Python编程思想》电子书,囊括了Python的核心技术,以及Python的主要函数库的使用方法。读者可以在「极客起源」 公众号中输入 160442 开始学习。

《Python编程思想》总目录
《Python编程思想》专栏

如果希望创建某一批类全部具有某种特征,则可以通过 metaclass来实现。使用 metaclass可以在创建类时动态修改类定义。为了使用 metaclass动态修改类定义,程序需要先定义 metaclass, metaclass应该继承type类,并重写new()方法。

下面程序定义了一个 metaclass类。

示例代码:metaclass_demo. py

# 定义MyMetaClass,继承type
class MyMetaClass(type):
    # cls代表动态修改的类
    # name代表动态修改的类名
    # bases代表被动态修改的类的所有父类
    # attr代表被动态修改的类的所有属性、方法组成的字典
    def __new__(cls, name, bases, attrs):
        # 动态为该类添加一个cal_price方法
        attrs['cal_price'] = lambda self: self.price * self.discount  # 折扣价
        return type.__new__(cls, name, bases, attrs)
# 定义House类
class House(metaclass=MyMetaClass):
    __slots__ = ('name', 'price', '_discount')
    def __init__(self, name, price):
        self.name = name
        self.price = price
    @property
    def discount(self):
        return self._discount
    @discount.setter
    def discount(self, discount):
        self._discount = discount


h = House("河畔小区", 2000000)
h.discount = 0.89
# 创建House对象的discount()方法
print(h.cal_price())

class Book(metaclass=MyMetaClass):
    __slots__ = ('name', 'price', '_discount')
    def __init__(self, name, price):
        self.name = name
        self.price = price
    @property
    def discount(self):
        return self._discount
    @discount.setter
    def discount(self, discount):
        self._discount = discount
b = Book("Python从菜鸟到高手", 128)
b.discount = 0.6
print(b.cal_price())

在这段代码中定义了House和Book两个类,在定义这两个类时都指定了 metaclass属性,因此当 Python解释器在创建这两个类时,MyMetaClass的new方法就会被调用,用于修改这两个类MyMetaClass类的new方法会为目标类动态添加 cal_price方法,因此,虽然在定义House和Book类时没有定义 cal_price方法,但这两个类依然有 cal_price方法。运行这段代码,会输出如下的内容:

1780000.0
76.8

从上面的输出结果来看,通过使用 metaclass可以动态修改程序中的一批类,对它们集中进行某种修改。这个功能在开发一些基础性框架时非常有用,程序可以通过使用 metaclass为某一批需要具有通用功能的类添加属性和方法。

-----------------支持作者请转发本文,也可以加李宁老师微信:unitymarvel,或扫描下面二维码加微信--------
在这里插入图片描述

欢迎关注 极客起源 微信公众号,更多精彩视频和文章等着你哦!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/nokiaguy/article/details/107012631