类型对象负责创建对象实例,控制对象行为。那么类型对象又由谁来创建呢?

元类(metaclass)——类型的类型

New-Style Class的默认类型是type

>>> class Data(object):
... pass
...
>>>
>>> Data.__class__
<type 'type'>
>>>
>>> type.__class__
<type 'type'> #最终的类型是type,包括type自己

关键字class会被编译成元类创建类型对象指令

>>> Data = type("Data",(object),{"x":1})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type() argument 2 must be tuple, not type
>>> Data = type("Data",(object,),{"x":1})#class的实际行为
>>>
>>> Data.x
1
>>> Data.__class__
<type 'type'>
>>>
>>> Data.__base__
<type 'object'>
class type(object)
| type(object) -> the object's type
| type(name, bases, dict) -> a new type

正因为class和def一样是指令,可以在任何地方创建类型对象。

>>> def test():
... class Data(object):pass
... return Data
...
>>>
>>> Data = test()
>>>
>>> Data.__name__
'Data'
>>>
>>> type(Data)
<type 'type'>
>>>
>>> Data()
<__main__.Data object at 0x7f822e1d2490>

元类、类型以及实例的创建顺序:

class = metaclass(....) #元类创建类型
instance = class(...) #类型创建实例 instance.__class__ is class #实例的类型
class.__class__ is metaclass #类型的类型

__metaclass__

除了使用默认元类type以外,还可以用__metaclass__属性指定自定义元类,以便对类型对象创建过程进行干预。

#!/usr/bin/env python26
#-*- coding:utf-8 -*- class InjectMeta(type):
def __new__(cls,name,bases,attrs):
t = type.__new__(cls,name,bases,attrs) def print_id(self):print hex(id(self)) t.print_id = print_id #为类型对象添加实例方法
t.s = "Hello,world!" #添加静态字段 return t class Data(object):
__metaclass__ = InjectMeta #显示指定元类 print Data.__metaclass__
print Data.__class__
print Data.s print dir(Data) Data().print_id()

输出:

<class '__main__.InjectMeta'>
<class '__main__.InjectMeta'>
Hello,world!
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'print_id', 's']
0x7f3687df7250

自定义元类通常都从type继承,习惯以Meta结尾。和继承有点类似。

只需注意__new和__init__方法参数的区别:

http://www.cnblogs.com/gsblog/p/3368304.html

当解释器创建类型对象时,会按以下顺序查找__metaclass__属性:

class.__metaclass__->bases.__metaclass__->module.__metaclass__->type

 magic

对象行为由类型决定。实例不过存储状态数据。控制类型对象的创建,也就意味着可以让对象的实际行为和代码存在极大的差异。这是魔法的力量。

静态类(static class):不允许创建实例。通常作为工具类(Utility)存在

[root@typhoeus79 20131014]# more static_class.py
#!/usr/bin/env python26
#-*- coding:utf-8 -*- class StaticClassMeta(type):
def __new__(cls,name,bases,attr):
t = type.__new__(cls,name,bases,attr) def ctor(cls,*args,**kwargs):
raise RuntimeError("Cannot be created a instance of the static class!")
t.__new__ = staticmethod(ctor) return t
class Data(object):
__metaclass__ = StaticClassMeta Data()
[root@typhoeus79 20131014]# ./static_class.py
Traceback (most recent call last):
File "./static_class.py", line 16, in <module>
Data()
File "./static_class.py", line 9, in ctor
raise RuntimeError("Cannot be created a instance of the static class!")
RuntimeError: Cannot be created a instance of the static class!

密封类(sealed class):禁止被继承

>>> class SealedClassMeta(type):
... _types = set()
... def __init__(cls,name,bases,attrs):
... if cls._types & set(bases):
... raise SyntaxError("Cannot inherit from a sealed class!")
... cls._types.add(cls)
...
>>>
>>> class A(object):
... __metaclass__ = SealedClassMeta
...
>>> class B(A):pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __init__
SyntaxError: Cannot inherit from a sealed class!

Python之元类的更多相关文章

  1. python 通过元类控制类的创建

    一.python中如何创建类? 1. 直接定义类 class A: a = 'a' 2. 通过type对象创建 在python中一切都是对象 在上面这张图中,A是我们平常在python中写的类,它可以 ...

  2. Python 的元类设计起源自哪里?

    一个元老级的 Python 核心开发者曾建议我们( 点击阅读),应该广泛学习其它编程语言的优秀特性,从而提升 Python 在相关领域的能力.在关于元编程方面,他的建议是学习 Hy 和 Ruby.但是 ...

  3. 关于python的元类

    当你创建一个类时: class Foo(Bar): pass Python做了如下的操作: Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__ ...

  4. Python的元类

    1.用元类验证子类 每当我们定义新类的时候,元类就会运行雅正代码,以确保这个新类符合规定的规范. Python系统把子类的class语句处理完毕,就会调用元类的 __new__ 方法.元类可以通过 _ ...

  5. 理解python的元类

    看了一篇文档,借鉴一下!写下自己对python元类的理解,欢迎各位大神给出意见. 我的理解就是 type用来创建元类,元类用来创建类,类用来创建实例 这样一想,是不是可以认为元类创建类的过程等同于类创 ...

  6. 【转】Python 之 元类

    原文链接: https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python      http://python.jo ...

  7. Python中元类

    元类(metaclass) 简单地说,元类就是一个能创建类的类,而类class 是由type创建的,class可以创建对象 type与object的关系详见:python中type和object 1. ...

  8. 转---一文读懂 python 的元类

    译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...

  9. Python之元类详细解析

    一.补充内置函数isinstance和issubclass 1.isinstance是判断一个对象是不是由一个对象产生的 class Foo: pass obj=Foo() print(isinsta ...

  10. Python之元类详解

    一.引子 元类属于Python面向对象编程的深层魔法,99%的人都不得要领,一些自以为搞明白元类的人其实也是自圆其说,点到为止,从队元类的控制上来看就破绽百出,逻辑混乱: 二.什么是元类 一切源自于一 ...

随机推荐

  1. 关于安全性问题:(XSS,csrf,cors,jsonp,同源策略)

    关于安全性问题:(XSS,csrf,cors,jsonp,同源策略) Ajax 是无需刷新页面就能从服务器获取数据的一种方法.它的核心对象是XHR,同源策略是ajax的一种约束,它为通信设置了相同的协 ...

  2. ASP.NET没有魔法——ASP.NET MVC 路由的匹配与处理

    ASP.NET MVC的路由是MVC应用的一个核心也是MVC应用处理的入口,作为一个开发者,在正常情况下仅仅需要做的就是根据需求去定义实体.业务逻辑,然后在MVC的Controller中去调用.Vie ...

  3. 笨鸟先飞之ASP.NET MVC系列之过滤器(05结果过滤器)

    概念介绍 结果过滤器看名字就知道这个过滤器是针对方法所产生结果的,结果过滤器,主要在我们的动作方法结果返回前后执行. 如果我们需要创建结果过滤器需要实现IResultFilter接口. namespa ...

  4. win10 UWP Markdown 含源代码

    Windows下没有比较好的Markdown编辑器 我就自己写一个 csdn的Markdown很好,就是我需要截图保存有麻烦 需要把我的截图保存在本地,然后上传 这个过程比较麻烦 csdn的图没法外链 ...

  5. Windows 10下Docker使用经验谈

    最近一直在开发Apworks框架的案例代码,同时也在一起修复Apworks框架中的Bug和一些设计上的不足.遇到的一个普遍问题是,代码的调试过程需要依赖很多外部系统,比如MongoDB.Postgre ...

  6. (转)HTTP1.0和HTTP1.1的区别

    原文出自:http://www.cnblogs.com/gofighting/p/5421890.html 1.HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(P ...

  7. C++虚函数(09)

    一旦基类定义了虚函数,该基类的派生类中的同名函数也自动称为虚函数. 虚函数只能是类中的一个成员函数,但不能是静态成员,关键字virtual用于类中该函数的声明中. 关键字virtual指示C++编译器 ...

  8. phalcon——HTTP 请求

    (一般在控制器方法中使用) 获取值: (1)直接获取值: $customerName = $this->request->getPost("name"); (2)自动添 ...

  9. LeetCode 170. Two Sum III - Data structure design (两数之和之三 - 数据结构设计)$

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  10. bootstrap折叠调用collapse()后data-parent不生效问题

    今天做的项目,用到了bootstrap的折叠功能,这个功能需要只展开一个折叠框,点击一个就会自动隐藏另一个,初始按照API做了一下,发现一切运行正常,但是测试的同事提了一个bug,说切换到其他模块后再 ...