1,__new__和__init__方法:
__new__方法限于新式类,是静态方法,且不是类方法,用来创建对象。
__init__方法是普通方法,用来初始化对象。
流程是(不完全正确): obj = classObj.__new__(classObj); type(obj).__init__(obj); (属性方法的访问,请参考前面的文章)
返回的obj可以和classObj没有任何关系,而且__new__至少会返回一个None对象,如果返回的type(obj)!=classObj,那么不会调用__init__方法。
class Singleton(object):
'单例的实现'
def __new__(cls, *args, **kwargs): # 静态方法,不要被cls给迷惑了
if not hasattr(cls, '_instance'): # 最终访问的还是object中的__new__方法,
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
def __init__(self, *args, **kwargs):
print self,args,kwargs
@staticmethod
def bar(self, *args, **kwargs):
print 'I am bar.',self
@classmethod
def foo(self, *args, **kwargs):
print 'I am foo.',self
obj1 = Singleton()
obj2 = Singleton()
Singleton._instance = 'I am not a foo.'
obj3 = Singleton()
print id(obj1),obj1,obj1.foo()
print id(obj2),obj2,obj2.foo()
print id(obj3),obj3
obj1.__new__() # 报错
obj1.bar() # 报错
obj1.foo()
Singleton.__new__() # 报错
Singleton.bar() # 报错
Singleton.foo()
2,__new__、__init__、__call__和__metaclass__:
首先清楚用于定制类的特殊方法,都是由类型进行调用,而不是实例,
如:a()等于type(a).__call__(a),而不是a.__call__()!!!
如:a+b等于type(a).__add__(a,b),而不是a.__add__(b)!!!
如:a = A()中对a的初始化,等于type(a).__init__(a),而不是a.__init__()!!!
看看__new__、__init__、__call__和__metaclass__之间的运作关系和机制,详解类和实例的创建过程:
class AA(object):
def __new__(self, *args, **kwargs):# 静态方法,self需要自己传递
print 'new in AA',args,kwargs
return super(AA, self).__new__(self, *args, **kwargs)
def __init__(self, *args, **kwargs):# 普通方法,self会自动绑定
print 'init in AA',args,kwargs
return super(AA, self).__init__(*args, **kwargs)
def __call__(self, *args,**kwargs): # 普通方法,self会自动绑定
print 'call in AA',args,kwargs
# return super(AA, self).__call__(*args,**kwargs)
class BB(type):
def __new__(self, name, bases, attrs):# 静态方法,self需要自己传递
print 'new in BB',name, bases, attrs
return super(BB, self).__new__(self, name, bases, attrs)
def __init__(self, *args, **kwargs):# 普通方法,self会自动绑定
print 'init in BB',args,kwargs
return super(BB, self).__init__(*args, **kwargs)
def __call__(self, *args,**kwargs): # 普通方法,self会自动绑定
print 'call in BB',args,kwargs
return super(BB, self).__call__(*args,**kwargs)
class CC(AA):
'一旦执行定义类CC的代码,就会调用BB元类中的__new__方法,其中真正生成类CC的是super(BB, self)中的__new__,也就是type中的__new__方法,检查返回对象是否是BB的实例,若是则调用type(CC).__init__(CC),也就是BB元类中的__init__方法,来初始化CC对象'
__metaclass__ = BB
def __new__(self, *args, **kwargs):# 静态方法,self需要自己传递
print 'new in CC',args,kwargs
return super(CC, self).__new__(self, *args, **kwargs)
def __init__(self, *args, **kwargs):# 普通方法,self会自动绑定
print 'init in CC',args,kwargs
return super(CC, self).__init__(*args, **kwargs)
def __call__(self, *args,**kwargs): # 普通方法,self会自动绑定
print 'call in CC',args,kwargs
return super(CC, self).__call__(*args,**kwargs)
c = CC()
c()
c = CC():BB中的__call__方法定义了对CC的调用行为,如同type(CC).__call__(CC),而不是CC.__call__(),然后BB中的__call__,等价于type.__call__,最终调用CC里面的__new__方法,CC的__new__方法调用AA的__new__方法,AA的__new__方法调用object中(不是type)的__new__方法生成并返回实例对象c。检查返回的对象c是否是CC的实例,若是则调用type(c).__init__(c),也就是CC元类中的__init__方法,来初始化c对象。
c():CC中的__call__方法定义了对c的调用行为,如同type(c).__call__(c),而不是c.__call__()
__metaclass__的查找和继承:先在CC中找__metaclass__属性,再在基类中找,再在其定义所在模块中找,最后使用默认的type来创建这个类对象,即类对象的默认__class__是type。
3,type中__new__来的动态创建类:
class Myclass(object):
def __new__(cls, *args,**kwargs):
tmp = super(type(cls),cls).__new__(cls, *args,**kwargs)
tmp.name = 'my name is lucy.'
return tmp
'---------or----------'
def __new2__(cls, *args,**kwargs):
tmp = super(type(cls),cls).__new__(cls, *args,**kwargs)
tmp.name = 'my name is lucy2.'
return tmp
Myclass2 = type('Myclass2',(object,),{'__new__':__new2__})
'---------or----------'
Myclass3 = type('Myclass3',(object,),{'name':'my name is lucy3.'})
@staticmethod
def __new3__(cls, *args,**kwargs):
return super(type(cls),cls).__new__(cls, *args,**kwargs)
Myclass3.__new__ = __new3__
a,b,c = Myclass(),Myclass2(),Myclass3()
print type(a),': ',a.name,' ',a.__dict__ # name在a的__dict__中
print type(b),': ',b.name,' ',b.__dict__ # name在b的__dict__中
print type(c),': ',c.name,' ',c.__dict__ # name在Myclass3的__dict__中
4,粘贴两个别人的例子,一个是关于hook,一个是关于orm:
def make_hook(f):
"""Decorator to turn 'foo' method into '__foo__' method """
f.is_hook = 1
return f
class MyType(type):
def __new__(cls, name, bases, attrs):
if name.startswith('None'):
return None
# Go over attributes and see if they should be renamed.
newattrs = {}
for attrname, attrvalue in attrs.iteritems():
if getattr(attrvalue, 'is_hook', 0):
newattrs['__%s__' % attrname] = attrvalue
else:
newattrs[attrname] = attrvalue
return super(MyType, cls).__new__(cls, name, bases, newattrs)
def __init__(self, name, bases, attrs):
super(MyType, self).__init__(name, bases, attrs)
# classregistry.register(self, self.interfaces)
print "Would register class %s now." % self
def __add__(self, other): # 定义类对象相加的行为,就是返回一个继承这两个类对象的类对象
class AutoClass(self, other):
pass
return AutoClass
# Alternatively, to autogenerate the classname as well as the class:
# return type(self.__name__ + other.__name__, (self, other), {})
def unregister(self):
# classregistry.unregister(self)
print "Would unregister class %s now." % self
class MyObject(object):
__metaclass__ = MyType
class NoneSample(MyObject):
pass
# Will print "NoneType None"
print type(NoneSample), repr(NoneSample)
class Example(MyObject):
def __init__(self, value):
self.value = value
@make_hook
def add(self, other): # 创建一个新的Example对象,
return self.__class__(self.value + other.value)
# Will unregister the class
Example.unregister()
inst = Example(10)
new_inst = inst + inst
print new_inst.value ,': inst的加法调用的是inst.__class__的__add__函数,也就是Example.__add__'
class Sibling(MyObject):
pass
ExampleSibling = Example + Sibling
# Example的加法调用的是Example.__class__的__add__函数,也就是MyType.__add__'
# ExampleSibling is now a subclass of both Example and Sibling (with no
# content of its own) although it will believe it's called 'AutoClass'
print ExampleSibling
print ExampleSibling.__mro__
' ORM 对象关系映射 '
class Field(object):
def __init__(self, name, column_type):
self.name = name
self.column_type = column_type
def __str__(self):
return '<%s:%s>' % (self.__class__.__name__, self.name)
class StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, 'varchar(100)')
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, 'bigint')
class ModelMetaclass(type):
def __new__(cls, name, bases, attrs):
if name=='Model':
return type.__new__(cls, name, bases, attrs)
print('Found model: %s' % name)
mappings = dict()
for k, v in attrs.iteritems():
if isinstance(v, Field):
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v
for k in mappings.iterkeys():
attrs.pop(k)
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
return type.__new__(cls, name, bases, attrs)
class Model(dict):
__metaclass__ = ModelMetaclass
def __init__(self, **kw):
super(Model, self).__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Model' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
def save(self):
fields = []
params = []
args = []
for k, v in self.__mappings__.iteritems():
fields.append(v.name)
params.append('?')
args.append(getattr(self, k, None))
sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
# testing code:
class User(Model):
id = IntegerField('uid')
name = StringField('username')
email = StringField('email')
password = StringField('password')
u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
u.save()
参考:
http://stackoverflow.com/questions/865911/is-everything-an-object-in-python-like-ruby
http://eli.thegreenplace.net/2012/03/30/python-objects-types-classes-and-instances-a-glossary/
https://docs.python.org/2/reference/datamodel.html
http://python.jobbole.com/82110/
(如果有什么说的不对的地方,欢迎大家多多批评指正。)