元类的介绍

请看位于下面网址的一篇文章,写的相当好。

http://blog.jobbole.com/21351/

实例补充

class Meta(type):
def __new__(meta, cls, parent, attr_dict):
res = super(Meta, meta).__new__(meta,cls, parent, attr_dict)
print('meta new stage, %s is %s, %s is %s' % (meta, type(meta), cls, type(cls)))
return res
def __init__(self,cls, parent, attr_dict):
super(Meta, self).__init__(cls,parent, attr_dict)
print('meta init stage, %s is %s, %s is %s' % (self, type(self), cls, type(cls)))
def __call__(self, *args, **kargs):
print('meta call stage, %s is %s' % (self, type(self)))
return super(Meta, self).__call__(*args, **kargs) def decorate(cls):
print('decorate cls, %s is %s' % (cls, type(cls)))
return cls @decorate
class A(metaclass=Meta):
def __new__(cls):
res = super(A, cls).__new__(cls)
print('A new stage, %s is %s' % (cls, type(cls)))
return res
def __init__(self):
super(A, self).__init__()
print('A init stage, %s is %s' % (self, type(self)))
def test(self):
pass
a=A()
print(a)

运行结果如下:

meta new stage, <class '__main__.Meta'> is <class 'type'>, A is <class 'str'>
meta init stage, <class '__main__.A'> is <class '__main__.Meta'>, A is <class 'str'>
decorate cls, <class '__main__.A'> is <class '__main__.Meta'>
meta call stage, <class '__main__.A'> is <class '__main__.Meta'>
A new stage, <class '__main__.A'> is <class '__main__.Meta'>
A init stage, <__main__.A object at 0x00000000022A74E0> is <class '__main__.A'>
<__main__.A object at 0x00000000022A74E0>

说明:

当我们自己创建一个类时,其实Python内部的运作机制如下:

  1. 看这个类中是否有设置元类,如果有,调用该元类进行初始化,如果没有,调用type进行初始化。
  2. 无论是我们自己定义的元类还是type,都有一个__new__方法,用来生成元类, 都有一个__init__用来初始化类。
  3. 查看是否有类的装饰器,如果有的话,调用之。

    其实,元类的__new____init__几乎什么都不做。

    当我们创建一个类的实例时,其实Python内部的运作机制如下:
  4. 调用元类的__call__方法,该方法会做两件事情:
  • 调用类自身的__new__方法用来创建类(如果有的话),如果我们没有显示的定义它,那么会调用从object继承过来的__new__方法。
  • 调用类自身的__init__方法(如果有的话)来初始化得到实例,如果我们没有显示的定义它,那么会调用从object继承过来的__init__方法。

    其实,object的__init__几乎什么都不做。

应用实例

由于我们经常在写类的内置拦截器方法时,少写下划线,或者出现拼写错误,从而怎么调试都不能发现问题所在,在浪费了很多时间以后才发现时犯的是多么低级的错误。

下面我写了这个元类来进行检查。

class AttrCheckMeta(type):
def __new__(meta, cls, parent, attr_dict):
import types
attrs_checking_list=['__init__', '__del__', '__call__', '__str__', '__repr__',
'__getattr__', '__setattr__', '__delattr__', '__getattribute__',
'__getitem__', '__setitem__', '__delitem__', '__iter__', '__next__',
'__contains__', '__get__', '__set__', '__delete__', '__lt__',
'__le__', '__gt__', '__ge__', '__eq__', '__add__', '__iadd__',
'__radd__', '__sub__', '__isub__', '__rsub__', '__mul__', '__imul__',
'__neg__', '__pos__', '__abs__', '__floordiv__', '__ifloordiv__',
'__truediv__', '__itruediv__', '__mod__', '__imod__', '__imod__',
'__pow__', '__ipow__', '__concat__', '__iconcat__', '__and__',
'__iand__', '__or__', '__ior__', '__xor__', '__ixor__', '__inv__',
'__invert__ ', '__lshift__', '__ilshift__', '__rshift__', '__irshift__ ',
'__bool__', '__len__', '__nonzero__', '__enter__', '__exit__',
'__new__', '__index__', '__oct__', '__hex__']
for attr,value in attr_dict.items():
#处理方法名前后都包含__,但是名字写错的情况。
if attr[:2]=='__' and attr[-2:]=='__' and isinstance(value, types.FunctionType):
if attr not in attrs_checking_list:
print('found problem function: %s' % attr)
#处理漏写后面__的情况,此时Python会把这个方法吗当成是需要扩张的方法。
elif attr.startswith('_'+cls+'__') and isinstance(value, types.FunctionType):
print('maybe has problem: %s' % attr) return super(AttrCheckMeta, meta).__new__(meta,cls, parent, attr_dict)
def __init__(self,cls, parent, attr_dict):
super(AttrCheckMeta, self).__init__(cls,parent, attr_dict)
def __call__(self, *args, **kargs):
return super(AttrCheckMeta, self).__call__(*args, **kargs) class A(metaclass=AttrCheckMeta):
def __new__(cls):
return super(A, cls).__new__(cls)
def __add(self, va, val):
pass
def __innit__(self):
super(A, self).__init__() a=A()

故意写了两个错误在类A中,运行结果如下:

found problem function name: __innit__
maybe has problem: _A__add

当然,这个可以用装饰器来完成同样的任务,而且装饰器似乎更加直白、容易理解。

代码如下:

def check_ol(cls):
'''the overloading function name is easily to have spelling mistake.
It will be very hard to find the related mistakes, so i use this automethod to check
It will print the possible mistakes once found, will do nothing if passed'''
import types
attrs_checking_list=['__init__', '__del__', '__call__', '__str__', '__repr__',
'__getattr__', '__setattr__', '__delattr__', '__getattribute__',
'__getitem__', '__setitem__', '__delitem__', '__iter__', '__next__',
'__contains__', '__get__', '__set__', '__delete__', '__lt__',
'__le__', '__gt__', '__ge__', '__eq__', '__add__', '__iadd__',
'__radd__', '__sub__', '__isub__', '__rsub__', '__mul__', '__imul__',
'__neg__', '__pos__', '__abs__', '__floordiv__', '__ifloordiv__',
'__truediv__', '__itruediv__', '__mod__', '__imod__', '__imod__',
'__pow__', '__ipow__', '__concat__', '__iconcat__', '__and__',
'__iand__', '__or__', '__ior__', '__xor__', '__ixor__', '__inv__',
'__invert__ ', '__lshift__', '__ilshift__', '__rshift__', '__irshift__ ',
'__bool__', '__len__', '__nonzero__', '__enter__', '__exit__',
'__new__', '__index__', '__oct__', '__hex__']
for attr,value in cls.__dict__.items():
#处理方法名前后都包含__,但是名字写错的情况。
if attr[:2]=='__' and attr[-2:]=='__' and isinstance(value, types.FunctionType):
if attr not in attrs_checking_list:
print('found problem function name: %s' % attr)
#处理漏写后面__的情况,此时Python会把这个方法吗当成是需要扩张的方法。
elif attr.startswith('_'+cls.__name__+'__') and isinstance(value, types.FunctionType):
print('maybe has problem: %s' % attr)
return cls

Python属性、方法和类管理系列之----元类的更多相关文章

  1. python day 11: 类的补充,元类,魔法方法,异常处理

    目录 python day 11 1. 类的补充 1.1 通过反射来查找类,创建对象,设置对象的属性与方法 1.2 类的魔法方法:getitem,setitem 1.3 元类__metaclass__ ...

  2. Python属性、方法和类管理系列之----属性初探

    在学习dict的时候,肯定听过dict是Python中最重要的数据类型,但是不一定知道为什么.马上你就会明白原因了. Python中从模块.到函数.到类.到元类,其实主要管理方法就是靠一个一个的字典. ...

  3. 类装饰器,元类,垃圾回收GC,内建属性、内建方法,集合,functools模块,常见模块

    '''''''''类装饰器'''class Test(): def __init__(self,func): print('---初始化---') print('func name is %s'%fu ...

  4. Python 属性方法、类方法、静态方法、 特殊属性__doc__ (内建属性)

    总结:和类的关联性讲:属性方法>类方法>静态方法 属性方法@property:仅仅是调用方式不用+括号. 类方法@classmethod:访问不了累的属性变量,只可以访问类变量. 静态方法 ...

  5. Python 爬取各大代理IP网站(元类封装)

    import requests from pyquery import PyQuery as pq base_headers = { 'User-Agent': 'Mozilla/5.0 (Windo ...

  6. Python说文解字_详解元类

    1.深入理解一切接对象: 1.1 什么是类和对象? 首先明白元类之前要明白什么叫做类.类是面向对象object oriented programming的重要概念.在面向对象中类和对象是最基本的两个概 ...

  7. Python元类实战,通过元类实现数据库ORM框架

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第19篇文章,我们一起来用元类实现一个简易的ORM数据库框架. 本文主要是受到了廖雪峰老师Python3入门教程的启 ...

  8. Delphi 类引用 Class Reference 元类 MetaClass 用法

    delphi中类引用的使用实例 类引用类引用(Class Reference)是一种数据类型,有时又称为元类(MetaClass),是类的类型的引用.类引用的定义形式如下: class of type ...

  9. Python属性、方法和类管理系列之----描述符类

    什么是描述符类? 根据鸭子模型理论,只要具有__get__方法的类就是描述符类. 如果一个类中具有__get__和__set__两个方法,那么就是数据描述符,. 如果一个类中只有__get__方法,那 ...

随机推荐

  1. Android_AsyncTask_DownloadImg_progressDIalog

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q ...

  2. [转]c#.NET和VB.NET语法的比较

    本文转自:http://www.cnblogs.com/lify0407/archive/2007/08/01/838589.html c#.NET和VB.NET语法的比较   VB.NET C# C ...

  3. 关于JFace中的对话框MessageDialog类等其它类型对话框

    对话框是软件系统中最常用到的界面,对话框无处不在,从界面结构来说,对话框主要是由主体的界面组件和底部窗体按钮组成. 之前的例子中已经频繁的使用到了MessageDialog.openInformati ...

  4. 在知乎回答的一个问题:C#初学者以后往WP开发走,还是往unity3d走?哪个更有前景呢

    问题原文:我是一个C#初学者,想问个问题,我以后是该往WP开发方向走呢还是学习Unity3D往游戏开发,哪个更有前景呢,个人感觉未来几年iOS,WP,Java会三足鼎立,WP现在有潜力,但是U3D现在 ...

  5. 20160502-struts2入门--国际化

    一.国际化 准备资源文件,资源文件的命名格式如下: baseName_language_country.properties baseName_language.properties baseName ...

  6. Android res资源文件夹的知识积累

    Android的开发框架耦合性还是比较低的,逻辑和布局被原生分开了.在Eclipse一般代码写在src文件夹下,资源等写在res文件夹下. drawable文件夹:该文件夹有很多变种,主要是为了适配A ...

  7. 转-----EasyCHM制作教程

    希望以后自己的笔记能够整理成 chm 格式的文档 制作过CHM帮助文件的同志们可能都遇到过以下两个问题: 1.制作好的CHM文件图像.公式不显示. 2.制作好的CHM文件在自己电脑上能显示,在别人电脑 ...

  8. Jquery中Ajax异步请求中的async参数的作用

    之前不知道这个参数的作用,上网找了前辈的博客,在此收录到自己的博客,希望能帮到更多的朋友: test.html <a href="javascript:void(0)" on ...

  9. 纯代码添加约束条件(Auto Layout)

    Auto Layout 是一种基于约束的.描述性的布局系统.也就是使用约束条件来描述布局,View的Frame会根据这些描述来进行计算. 在iOS6.0以后加入了一个新类: NSLayoutConst ...

  10. iOS 各种控件默认高度

    1.状态栏 状态栏一般高度为20像素,在打手机或者显示消息时会放大到40像素高,注意,两倍高度的状态栏在好像只能在纵向的模式下使用.如下图   用户可以隐藏状态栏,也可以将状态栏设置为灰色,黑色或者半 ...