python3 之metaclass
如果希望创建某一批类全部具有某种特征,则可通过 metaclass 来实现。使用 metaclass 可以在创建类时动态修改类定义。
为了使用 metaclass 动态修改类定义,程序需要先定义 metaclass, metaclass 应该继承 type 类,并重写 __new__() 方法。
下面程序定义了一个 metaclass 类:
#定义ItemMetaClass,继承type
class ItemMetaClass(type):
# cls 代表动态修改的类
# name 代表动态修改的类名
# bases 代表被动态修改的类的所有父类
# attrs 代表被动态修改的类的所有属性、方法组成的字典 def __new__(cls, name, bases, attrs):
#动态为该类添加一个cal_price方法
attrs['cal_price'] = lambda self:self.price * self._discount
return type.__new__(cls, name, bases, attrs)
上面程序定义了一个 ItemMetaClass 类,该类继承了 type 类,并重写了 __new__ 方法,在重写该方法时为目标类动态添加了一个 cal_price 方法。
metaclass 类的 __new__ 方法的作用是:当程序使用 class 定义新类时,如果指定了 metaclass,那么 metaclass 的 __new__ 方法就会被自动执行。
例如,如下程序使用 metaclass 定义了两个类:
#定义book类
class Book(metaclass=ItemMetaClass):
__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 #定义cellPhone类
class CellPhone(metaclass=ItemMetaClass):
__slots__ = ('price', '_discount')
def __init__(self, price):
self.price = price @property
def discount(self):
return self._discount @discount.setter
def discount(self, discount):
self._discount = discount
上面程序定义了 Book 和 CellPhone 两个类,在定义这两个类时都指定了 metaclass 信息,因此当 Python 解释器在创建这两个类时,ItemMetaClass 的 __new__ 方法就会被调用,用于修改这两个类。
ItemMetaClass 类的 __new__ 方法会为目标类动态添加 cal_price 方法,因此,虽然在定义 Book、CellPhone 类时没有定义 cal_price() 方法,但这两个类依然有 cal_price() 方法。如下程序测试了 Book、CellPhone 两个类的 cal_price() 方法:
#Book类实例化
b = Book('Python基础教程', 89)
b.discount = 0.8
#Book类的cal_price()方法
print(b.cal_price()) #CellPhone类实例化
cp = CellPhone(2300)
cp.discount = 0.85
#CellPhone类的cel_price方法
print(cp.cal_price())
输出结果如下:
71.2
1955.0
python3 之metaclass的更多相关文章
- Python学习笔记:单例模式
单例模式:一个类无论实例化多少次,返回的都是同一个实例,例如:a1=A(), a2=A(), a3=A(),a1.a2和a3其实都是同一个对象,即print(a1 is a2)和print(a2 is ...
- python3全栈开发- 元类metaclass(面试必考题)
一.知识储备 #exec:三个参数 #参数一:字符串形式的命令 #参数二:全局作用域(字典形式),如果不指定,默认为globals() #参数三:局部作用域(字典形式),如果不指定,默认为locals ...
- python3(三十一)metaclass
""" """ __author__ = 'shaozhiqi' # 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而 ...
- 【转】Python3.x和Python2.x的区别
这个星期开始学习Python了,因为看的书都是基于Python2.x,而且我安装的是Python3.1,所以书上写的地方好多都不适用于Python3.1,特意在Google上search了一下3.x和 ...
- Python2.x与Python3.x的区别
这个星期开始学习Python了,因为看的书都是基于Python2.x,而且我安装的是Python3.1,所以书上写的地方好多都不适用于Python3.1,特意在Google上search了一下3.x和 ...
- 【转载】python3.0与2.x之间的区别
python3.0与2.x之间的区别: 1.性能 Py3.0运行pystone benchmark的速度比Py2.5慢30%.Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可以取得很好 ...
- Python3 ORM hacking
#!/usr/bin/env python3 # -*- coding: utf- -*- # # Python3 ORM hacking # 说明: # 之前分析了一个Python2 ORM的源代码 ...
- Python3中的新特性(1)——新的语言特性
1.源代码编码和标识符 Python3假定源代码使用UTF-8编码.另外,关于标识符中哪些字符是合法的规则也放宽了.特别是,标识符可以包含代码点为U+0080及以上的任意有效Unico ...
- python3.0与2.x之间的区别
python3.0与2.x之间的区别: 1.性能 Py3.0运行pystone benchmark的速度比Py2.5慢30%.Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可以取得很好 ...
随机推荐
- 开发QQ互联ios版Ane扩张 辛酸史
来源:http://www.myexception.cn/operating-system/1451490.html 开发QQ互联ios版Ane扩展 辛酸史 开发QQ互联ios版Ane扩展辛酸史: 1 ...
- windows下使用virtualenv对python进行多版本隔离开发
1.windows下安装virtualenv pip install virtualenv 2.进入项目目录,创建虚拟环境,例如: virtualenv venv (默认python版本) virtu ...
- SQL SERVER-SSMS安装联机丛书 book online
1.下载地址:https://www.microsoft.com/en-us/download/details.aspx?id=42557 2.解压. 3.在SSMS中添加引用. 选择解压路径找到ms ...
- 使用awstats分析nginx日志
1.awstats介绍 本文主要是记录centos6.5下安装配置awstats,并统计nginx访问日志 1.1 awstats介绍 awstats是一款日志统计工具,它使用Perl语言编写,可统计 ...
- nginx_status
server { listen ; server_name blog.oldboy.com; root /code/wordpress; index index.php index.html; loc ...
- MySQL 空事务
问题描述; 研发同事反应MySQL数据库有锁,检查innodb_trx时,发现有很多长时间未结束的空事务. 这些事务的trx_mysql_thread_id都为0,因此不能通过kill ...
- ashx 文件的运用
ASP.NET中有一种这样格式的文件ashx文件,作什么用的呢?如果你想创建一个ASP.NET文件,它不是aspx文件,它能动态的返回一个图片.XML文件或其他非HTML文件.那就使用ashx文件了. ...
- abp学习(一)
官网概念 ASP.NET样板是特别设计的新的现代Web应用程序的通用应用框架.它使用已经熟悉的工具并围绕这些工具实现最佳实践,从而为您提供一致的开发体验. 官网地址:https://aspnetboi ...
- centos7 安装 mongodb 4.0.0
原文链接:http://www.webosss.com/article/detail/38 下载mongodb:地址:https://fastdl.mongodb.org/linux/mongodb- ...
- Problem G: STL——整理唱片(list的使用)
#include<iostream> #include<list> #include<iterator> #include<algorithm> usi ...