举例讲解Python中metaclass元类的创建与使用


Posted in Python onJune 30, 2016

元类是可以让你定义某些类是如何被创建的。从根本上说,赋予你如何创建类的控制权。
元类也是一个类,是一个type类。
 
元类一般用于创建类。在执行类定义时,解释器必须要知道这个类的正确的元类,如果此属性没有定义,它会向上查找父类中的__metaclass__属性。如果还没发现,就查找全局变量。
 
对于传统类来说,它们的元类是types.ClassType。
 
元类也有构造器,传递三个参数:类名,从基类继承数据的元组,和类属性字典。
下面我们来定义一个元类,要求写类的时候必须给类提供一个__str__()方法,如果没有提供__repr__()方法,
则给你警告。

from warnings import warn
#元类需要继承type类
class ReqStrSugRepr(type):
  def __init__(cls, name, bases, attrd):
  #构造函数需要传递的参数为类名,基类,类属性字典
    super(ReqStrSugRepr, cls).__init__(name, bases, attrd)
    # 判断__str__字符串是否在类的属性字典里
    if '__str__' not in attrd:
      raise TypeError('Class requires overriding of __str__()')

    if '__repr__' not in attrd:
      warn('Class suggests overriding of __repr__()\n', stacklevel=3)

class Foo(object):
  #给类指定元类 
  __metaclass__ = ReqStrSugRepr

  def foo(self):
    pass
#这一段代码不用创建类来测试,直接运行一下就会报错,可见元类的功力。

举例讲解Python中metaclass元类的创建与使用

type

type函数可以查看一个变量的类型, 比如:

# <type 'int'>
# <type 'str'>
type(1)     
type('mink')

type函数还可以创建一个新的对象
type接受三个参数,name, bases, dict 第一个接受类名,第二个参数接受父类(元组形式),第三个参数接受属性和方法(字典形式)

X = type('X', (object,), dict(a=1))
# 等于
class X(object):
  a = 1

下面是接受函数的方法

def say(self):
  print 'hello'

X = type('X', (object,), dict(say=say))
x = X()

# pirnt hello
x.say()

元类

我们都知道通过类可以创建处实例对象,而元类就是创建出类对象的类。type可以创建出类对象也就是说type就是一个元类。

metaclass 属性

如果想使用元类创建类对象就需要对该对象添加一个__metaclass__属性。当然你首先得有一个元类

class PrivateMetaclass(type):
  def __new__(cls, name, parents, attrs):
    attrs = dict(('__%s' % k, v) for k, v in attrs.itmes())
    return super(PrivateMetaclass, cls).__new__(cls, name, parents, attrs)

class A(object):
  __metaclass__ = PrivateMetaclass
  a = 1
  b = 2

a = A()
# raise AttributeError
print a.a, a.b 

# print 1, 2
print a.__a, a.__b

这样你就可以通过元类来修改类的一些特性,上面的就是修改变量为私有变量.

Python 相关文章推荐
对于Python的Django框架使用的一些实用建议
Apr 03 Python
Python函数中的函数(闭包)用法实例
Mar 15 Python
解决PyCharm中光标变粗的问题
Aug 05 Python
python读写Excel表格的实例代码(简单实用)
Dec 19 Python
python cv2截取不规则区域图片实例
Dec 21 Python
python @propert装饰器使用方法原理解析
Dec 25 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
Jan 02 Python
如何在Python 游戏中模拟引力
Mar 27 Python
Python如何优雅删除字符列表空字符及None元素
Jun 25 Python
Python如何实现线程间通信
Jul 30 Python
使用numpy实现矩阵的翻转(flip)与旋转
Jun 03 Python
Python语言内置数据类型
Feb 24 Python
在Python中定义和使用抽象类的方法
Jun 30 #Python
Python中functools模块的常用函数解析
Jun 30 #Python
深入浅析Python中join 和 split详解(推荐)
Jun 30 #Python
Python列出一个文件夹及其子目录的所有文件
Jun 30 #Python
django之常用命令详解
Jun 30 #Python
全面了解Python环境配置及项目建立
Jun 30 #Python
浅谈Python 集合(set)类型的操作——并交差
Jun 30 #Python
You might like
PHP面向对象法则
2012/02/23 PHP
php中error与exception的区别及应用
2014/07/28 PHP
写一段简单的PHP建立文件夹代码
2015/01/06 PHP
PHP使用PDO实现mysql防注入功能详解
2019/12/20 PHP
JS对URL字符串进行编码/解码分析
2008/10/25 Javascript
javascript模拟实现C# String.format函数功能代码
2013/11/25 Javascript
jquery插件jTimer(jquery定时器)使用方法
2013/12/23 Javascript
浅谈JS闭包中的循环绑定处理程序
2014/11/09 Javascript
Javascript中setTimeOut和setInterval的定时器用法
2015/06/12 Javascript
IE浏览器下PNG相关功能
2015/07/05 Javascript
JavaScript实现动态删除列表框值的方法
2015/08/12 Javascript
微信js-sdk上传与下载图片接口用法示例
2016/10/12 Javascript
Bootstrap基本组件学习笔记之缩略图(13)
2016/12/08 Javascript
js实现自定义路由
2017/02/04 Javascript
详解让sublime text3支持Vue语法高亮显示的示例
2017/09/29 Javascript
vue 组件中添加样式不生效的解决方法
2018/07/06 Javascript
解决axios发送post请求返回400状态码的问题
2018/08/11 Javascript
JS实现方形抽奖效果
2018/08/27 Javascript
js指定日期增加指定月份的实现方法
2018/12/19 Javascript
详解原生JS动态添加和删除类
2019/03/26 Javascript
Vue Element UI + OSS实现上传文件功能
2019/07/31 Javascript
JS实现分页导航效果
2020/02/19 Javascript
react 不用插件实现数字滚动的效果示例
2020/04/14 Javascript
JS严格模式原理与用法实例分析
2020/04/27 Javascript
解决ant Design中Select设置initialValue时的大坑
2020/10/29 Javascript
[01:00:12]2018DOTA2亚洲邀请赛 4.7 淘汰赛 VP vs LGD 第一场
2018/04/09 DOTA
[04:00]黄浦江畔,再会英雄——完美世界DOTA2 TI9应援视频
2019/07/31 DOTA
python机器学习之随机森林(七)
2018/03/26 Python
经典c++面试题五
2014/12/17 面试题
升旗仪式演讲稿
2014/05/08 职场文书
大学生入党推荐书范文
2014/05/17 职场文书
体育教育毕业生自荐信
2014/06/29 职场文书
在职证明书范本(2014新版)
2014/09/25 职场文书
2015年基层党建工作总结
2015/05/14 职场文书
大学班干部竞选稿
2015/11/20 职场文书
Java9新特性对HTTP2协议支持与非阻塞HTTP API
2022/03/16 Java/Android