首页 > 学院 > 开发设计 > 正文

new、init和metaclass

2019-11-08 01:03:04
字体:
来源:转载
供稿:网友

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.',selfobj1 = 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),obj3obj1.__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 tmpMyclass2 = type('Myclass2',(object,),{'__new__':__new2__})'---------or----------'Myclass3 = type('Myclass3',(object,),{'name':'my name is lucy3.'})@staticmethoddef __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 fclass 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." % selfclass MyObject(object):    __metaclass__ = MyTypeclass 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 classExample.unregister()inst = Example(10)new_inst = inst + instprint new_inst.value ,': inst的加法调用的是inst.__class__的__add__函数,也就是Example.__add__'class Sibling(MyObject):    passExampleSibling = 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 ExampleSiblingprint 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/100003/what-is-a-metaclass-in-pythonhttp://stackoverflow.com/questions/865911/is-everything-an-object-in-python-like-rubyhttp://eli.thegreenplace.net/2012/03/30/python-objects-types-classes-and-instances-a-glossary/https://docs.python.org/2/reference/datamodel.htmlhttp://python.jobbole.com/82110/

(如果有什么说的不对的地方,欢迎大家多多批评指正。)


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表