new、init和metaclass

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/100003/what-is-a-metaclass-in-python
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/


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值