专栏首页极客起源Python编程思想(30):用 metaclass搞定一批类的特性

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

如果希望创建某一批类全部具有某种特征,则可以通过 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为某一批需要具有通用功能的类添加属性和方法。

本文分享自微信公众号 - 极客起源(geekculture),作者:geekori

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-07-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python编程思想(28):限制类的动态特性(__slots__属性)

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

    蒙娜丽宁
  • Python编程思想(26):成员变量

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

    蒙娜丽宁
  • 微信小程序开发实战(13):图像组件(image)

    image可以用来显示图像,这些图像可以是本地的,也可以是网络图像。例如,下面的布局代码显示了本地图像。

    蒙娜丽宁
  • iOS开发·状态栏设置技巧2:更新状态栏

    info.plist文件中有个一项:View controller-based status bar appearance:

    陈满iOS
  • 写个localStorage的小例子

    我在搜狗问问帮别人写代码的时候遇到一个小的问题,问题是这样的,就是题主希望在别的页面获取到前一个页面存在js里面的数据,这个时候一般都会想到的是用cookie,...

    何处锦绣不灰堆
  • 聊聊flink的StateDescriptor

    flink-core-1.7.0-sources.jar!/org/apache/flink/api/common/functions/RuntimeConte...

    codecraft
  • 聊聊flink的StateDescriptor

    flink-core-1.7.0-sources.jar!/org/apache/flink/api/common/functions/RuntimeConte...

    codecraft
  • bootstrap typeahead 异步从后台提取数据 常用 *

    <!doctype html> <html> <head> <meta charset="utf-8"> <title>联想控股</title> <m...

    用户5760343
  • 如何在Java代码中使用SAP云平台CloudFoundry环境的环境变量

    版权声明:本文为博主汪子熙原创文章,未经博主允许不得转载。 https://jerry.blog....

    Jerry Wang
  • React之JSX语法

    如果要使用JSX,需要得到语法的支持,你可以使用Babel来进行转换。在该篇文章当中直接引入Babel文件。 将上一篇文章的“你好,世界”拿过来看一下:

    用户1272076

扫码关注云+社区

领取腾讯云代金券