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

元类(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!

最新文章

  1. C#非常重要基础之多态
  2. MYSQL 常用函数(数学、字符串、日期时间、系统信息、加密)
  3. Laplacian matrix 从拉普拉斯矩阵到谱聚类
  4. eclipse中的任务标记(TODO、FIXME、XXX)
  5. Linux Strip
  6. Spring 一二事(1)
  7. 情报收集:Metasploit命令、查询网站和测试网站
  8. HDU 4118 Holiday&#39;s Accommodation
  9. 翻译【ElasticSearch Server】第一章:开始使用ElasticSearch集群(4)
  10. 《Programming WPF》翻译 第5章 2.内嵌样式
  11. hdu5863 cjj's string game
  12. CAS简介和无锁队列的实现
  13. Beta No.6
  14. Tomcat和JDK的内存配置
  15. Pythoy 数据类型序列化——json&amp;pickle 模块
  16. 孤儿进程VS僵尸进程
  17. eclipse invalid zip archive lib
  18. Java SE之正则表达式五:切割
  19. MySQl创建用户和授权
  20. 升级 Centos 6.5/6.7 的 php 版本

热门文章

  1. HDU3336 Count the string
  2. java 学习笔记 读取配置文件的三种方式
  3. 压缩SQLServer数据库日志的一个存储过程
  4. zabbix部署
  5. DevOps之基础设施
  6. Scala-Spark digamma stackoverflow问题
  7. 干了这杯Java之Vector
  8. Hadoop(八)Java程序访问HDFS集群中数据块与查看文件系统
  9. UVa10129,Play On Words
  10. faster-rcnn中ROI_POOIING层的解读