美文网首页
元类编程

元类编程

作者: xin激流勇进 | 来源:发表于2018-08-19 17:20 被阅读0次

    http://blog.jobbole.com/21351/
    https://segmentfault.com/a/1190000011447445

    proprety简单用法

    from datetime import date, datetime
    
    
    class User:
        def __init__(self, name, birthday):
            self.name = name
            self.birthday = birthday
    
        def get_age(self):
            return datetime.now().year - self.birthday.year
    
        @property
        def age(self):
            return datetime.now().year - self.birthday.year
    
        @age.setter
        def age(self, value):
            self.name = value
    
    
    if __name__ == '__main__':
        user = User('Merry', date(year=1996, month=10, day=24))
        print(user.age)
        user.age = 'Bob'
    

    getattrgetattribution

    from datetime import datetime
    from yuanlei import test
    
    # print(getattr(test, 'Name'))
    
    
    class User:
        def __getattr__(self, item):
            '''找不到类属性时调用'''
            return datetime.now()
    
        def __getattribute__(self, *args, **kwargs):
            '''无条件被调用,通过实例访问属性。
            如果class中定义了__getattr__(),
            则__getattr__()不会被调用(
            除非显示调用或引发AttributeError异常) '''
    
            print('in the getattribute')
            return object.__getattribute__(self, *args, **kwargs)
    
    #
    # user = User()
    # print(getattr(user, 'a'))
    
    class C(object):
        a = 'abc'
    
        def __getattribute__(self, *args, **kwargs):
            print("__getattribute__() is called")
            return object.__getattribute__(self, *args, **kwargs)
    
        #        return "haha"
        def __getattr__(self, name):
            print("__getattr__() is called ")
            return name + " from getattr"
    
        def __get__(self, instance, owner):
            '''如果class定义了它,则这个class就可以称为descriptor。
            owner是所有者的类,instance是访问descriptor的实例,
            如果不是通过实例访问,而是通过类访问的话,instance则为None。
            (descriptor的实例自己访问自己是不会触发__get__,而会触发__call__,
            只有descriptor作为其它类的属性才有意义。)
            (所以下文的d是作为C2的一个属性被调用) '''
            print("__get__() is called", instance, owner)
            return self
    
        def foo(self, x):
            print(x)
    
    
    class C2(object):
        d = C()
    
    
    if __name__ == '__main__':
        # c = C()
        c2 = C2()
        # print(c.a)
        # print(c.zzzzzzzz)
        c2.d
        # print(c2.d.zzzz)
    

    属性描述符

    '''
    如果user是某个类的实例,那么user.age(以及等价的getattr(user,’age’))
    首先调用__getattribute__。如果类定义了__getattr__方法,
    那么在__getattribute__抛出 AttributeError 的时候就会调用到__getattr__,
    而对于描述符(__get__)的调用,则是发生在__getattribute__内部的。
    user = User(), 那么user.age 顺序如下:
    
    (1)如果“age”是出现在User或其基类的__dict__中, 且age是data descriptor, 那么调用其__get__方法, 否则
    
    (2)如果“age”出现在user的__dict__中, 那么直接返回 obj.__dict__[‘age’], 否则
    
    (3)如果“age”出现在User或其基类的__dict__中
    
    (3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则
    
    (3.2)返回 __dict__[‘age’]
    
    (4)如果User有__getattr__方法,调用__getattr__方法,否则
    
    (5)抛出AttributeError
    
    '''
    import numbers
    
    class IntField:
        def __set__(self, instance, value):
            if isinstance(value, numbers.Integral):
                self.value = value
            else:
                raise ValueError('value is not int')
    
        def __get__(self, instance, owner):
            return self.value
    
    
    class User:
        age = IntField()
    
    
    user = User()
    user.age = 22
    print(user.age)
    print(user.__dict__)
    
    

    动态生成类

    # class Hello:
    #     def say_hello(self, name='world'):
    #         print('hello %s' % name)
    
    
    def say_hello(self, name='world'):
        print('hello %s' % name)
    
    Hello = type('Hello', (object,), {'say_hello': say_hello})
    print(Hello)
    
    hello = Hello()
    hello.say_hello()
    

    元类

    class SayMetaClass(type):
    
        def __new__(cls, name, bases, attrs, **kwargs):
            attrs['say_'+name] = lambda self, value, saying=name: print(saying+','+value+'!')
            # print(attrs)
            return super().__new__(cls, name, bases, attrs, **kwargs)
    
    
    class Hello(object, metaclass=SayMetaClass):
        name = 'chen'
    
        def get_age(self):
            return 22
    
    class Hi(metaclass=SayMetaClass):
        pass
    
    # hello = Hello()
    # hi = Hi()
    # hello.say_Hello('Nihao')
    # hi.say_Hi('HI')
    
    class ListMetaclass(type):
        def __new__(cls, name, bases, attrs, **kwargs):
            attrs['add'] = lambda self, value: self.append(value)
            return super().__new__(cls, name, bases, attrs, **kwargs)
    
    
    class MyList(list, metaclass=ListMetaclass):
        pass
    
    L = MyList()
    L.add(1)
    L.add(2)
    print(L)
    

    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().__init__(name, 'varchar(100)')
    
    
    class IntegerField(Field):
        def __init__(self, name):
            super().__init__(name, 'bigint')
    
    
    class ModelMetaclass(type):
    
        def __new__(cls, name, bases, attrs):
            if name == 'Model':
                return super().__new__(cls, name, bases, attrs)
    
            print('Found model: %s' % name)
            mappings = dict()
            for k, v in attrs.items():
                if isinstance(v, Field):
                    print('Found mapping: %s==>%s' % (k, v))
                    mappings[k] = v
            for k in mappings.keys():
                attrs.pop(k)
    
            attrs['__mappings__'] = mappings
            attrs['__table__'] = name
            return super().__new__(cls, name, bases, attrs)
    
    
    class Model(dict, metaclass=ModelMetaclass):
    
        def __getattr__(self, key):
            try:
                return self[key]
            except KeyError:
                raise AttributeError("'Model' object has no attribute '%s'" % key)
    
        def __setattr__(self, key, value):
            self[key] = value
    
        def save(self):
            fields = []
            args = []
            for k, v in self.__mappings__.items():
                fields.append(v.name)
                args.append(getattr(self, k, None))
            sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join([str(i) for i in args]))
            print('SQL: %s' % sql)
            print('ARGS: %s' % str(args))
    
    
    class User(Model):
        id = IntegerField('id')
        name = StringField('username')
        email = StringField('email')
        password = StringField('password')
    
    
    u = User(id=12345, name='Batman', email='batman@nasa.org', password='iamback', test=123)
    u.id = 100
    u.save()
    
    
    

    相关文章

      网友评论

          本文标题:元类编程

          本文链接:https://www.haomeiwen.com/subject/lxhciftx.html