美文网首页
Python类-元编程Meta programming, sin

Python类-元编程Meta programming, sin

作者: Mc杰夫 | 来源:发表于2022-01-30 11:10 被阅读0次

    (2022.01.30 Sun 除夕前夜)
    开发者总要铭记: DRY, i.e., Don’t Repeat Yourself。代码复用成为关键环节。

    在Python中使用元编程Meta programming解决复用问题。Meta programming is the concept of building functions or classes whose primary target is to manipulate code by modifying, wrapping or generating existing codes.元编程就是用已有的代码控制和生成新的代码。

    元编程的几个典型特征:

    • 元类Metaclass
    • 装饰器Decorator
    • 类装饰器class decorator

    元编程的优点是debug被隔离在特定位置,方便了debug,也方便了修改和disable。

    先来看看python中的类和对象。

    type、类和对象

    Python中有一句话是 Everything is an object万物皆对象。函数,类,内置类型,都是对象。而类/对象来自于何处呢?

    我们来验证类和对象的类型

    >>> class SomeClass:
    ...     pass
    ... 
    >>> a = SomeClass()
    >>> type(a)
    <class '__main__.SomeClass'>
    >>> type(SomeClass)
    <class 'type'>
    >>> type(type)
    <class 'type'>
    

    inspect工具判断对象是否为类,或者非类

    >>> import inspect
    >>> inspect.isclass(SomeClass)
    True
    >>> inspect.isclass(a)
    False
    >>> inspect.isclass(type)
    True
    

    从上面的结果可以看到一个类的实例,其类型是该类。该类的类型是typetype的类型是其本身,并且type本身也是一个类。

    >>> isinstance(a, SomeClass)
    True
    >>> isinstance(a, type)
    False
    >>> isinstance(SomeClass, type)
    True
    >>> isinstance(type, type)
    True
    

    # 2022.03.16 Wed, also available to other types, e.g., str, float and etc
    >>> age = 5
    >>> age.__class__
    <class 'int'>
    >>> age.__class__.__class__
    <class 'type'>
    

    一个实例是实例化的类,一个类是实例化的元类metaclass,也就是type。(2022.03.17 Thur)在面向对象的编程中,元类的实例还是类。

    type本身是一个类,是Python内置的metaclass元类。我们可以自定义metaclass,所有类和元类都从type继承而来。元类是Python元编程的方式之一。

    type-meta-class.jpg

    type创建类

    type是Python中类的元类,因此可用type创建类。创建格式如下

    <new_class_name> = type(<new_class_name>, [<base_class>], {<class_method1>: method_name_1, <class_var1>: var_value, ...})

    如,创建一个叫classBase的类,没有内置方法和变量

    >>> classBase = type('classBase', (), {}) 
    # 第二个参数只能是tuple格式,其中数值为空表示继承自type,
    # 第三个是字典格式,用于标记类方法和类变量
    

    classBase类创建其他类(非实例化),即继承。注意,如果通过type创建的类没有实例化,则定义语句外的方法声明中不需要含有self参数。

    >>> def func(argu1, argu2):
    >>>    return 'something'
    >>> newClass = type('newClass', (classBase,), {'method1': func, 'var': 5})
    # 第二个参数别忘记逗号
    >>> print(newClass.var) 
    5
    >>> print(newClass.method1(1, 2))
    'something'
    

    list类定义一个新类,该类不仅有list的内置方法,还可以自定义类变量和类方法。注意,通过type定义的类,一旦其被实例化,自定义的方法声明中需要有self参数。

    >>> def func(self, arg1):
    ...     return str(arg1)+' is a string.'
    ... # 定义这个函数时需要加self参数
    >>> newList = type('newList', (list, ), {'var': 99, 'display': func})
    >>> a = newList() # instantiation
    >>> type(a)
    <class '__main__.newList'>
    >>> a.append(1)
    >>> print(a)
    [1]
    >>> a.var
    99
    >>> a.display('bbb')
    'bbb is a string.'
    

    (2022.03.16 Wed)
    type创建/继承类,其优点在于可以“动态”的创建类。比如上面的newList对象,如果按常规的类创建方式可以写成如下形式。修改方法或添加方法都需要重写类。

    class newList:
        var = 99
        def __init__(self):
            pass
        def display(self, arg1):
            return str(arg1)+' is a string.'
    

    (2022.03.17 Thur)
    也可以自己定义元类,自定义元类是type类的继承。下面例子展示了如何自定义元类,该自定义元类为继承它的子类创建了hello方法,子类无需定义即可继承该方法。

    class helloMeta(type): # 这里有对type类的继承
        def hello(cls):
            print('helloMeta class')
        def __call__(self, *args, **kwargs):
            cls = type.__call__(self, *args)
            setattr(cls, 'hello', self.hello)
            return cls
    
    class tryHello(object, metaclass=helloMeta): #这里的两个参数必不可少
        def greet(self):
            self.hello()
    

    调用

    >>> t = tryHello()
    >>> t.greet()
    helloMeta class
    

    typeobject的区别

    (2022.05.18 Wed)
    object是所有类的父类,type也是继承了object类。在Python3.x中,所有类的创建默认情况下,即class cn:语句,都是从object继承类,只有标注了type才是从type继承类,如class cn(type):。相比继承自type的类,继承自object的类内置方法更少。

    通过__mro__方法或mro可以查看一个类的继承顺序/方法解析顺序(Method Resolution Order)。可以看到如果类继承自type类,会最终继承object类。

    class a(object):
        pass
    class b:
        pass
    class c(type):
        pass
    
    >> a.__mro__
    (__main__.a, object)
    >> b.__mro__
    (__main__.b, object)
    >> c.__mro__
    (__main__.c, type, object)
    >> dir(a)
    ['__class__',  '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
     '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
     '__lt__', '__module__', '__ne__', '__new__',
     '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
     '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
    >> dir(c)
    ['__abstractmethods__', '__base__', '__bases__', '__basicsize__',
     '__call__', '__class__', '__delattr__', '__dict__',
     '__dictoffset__', '__dir__', '__doc__', '__eq__',
     '__flags__', '__format__', '__ge__', '__getattribute__',
     '__gt__', '__hash__', '__init__', '__init_subclass__',
     '__instancecheck__', '__itemsize__', '__le__', '__lt__',
     '__module__', '__mro__', '__name__', '__ne__',
     '__new__', '__prepare__', '__qualname__', '__reduce__',
     '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
     '__str__', '__subclasscheck__',  '__subclasses__', '__subclasshook__',
     '__text_signature__', '__weakrefoffset__', 'mro']
    

    object类的类型是type

    >> type(a)
    type
    

    元类的应用场景1: 实现单例模式

    (2022.03.16 Wed)
    我们用元类形式实现单例模式。另外,装饰器也可实现单例模式。

    class Singleton(type): #这里一定要有type关键字表明其继承元类
        def __init__(cls, name, bases, dic):
            super(Singleton, cls).__init__(name, bases, dic)
            cls.instance = None
        def __call__(cls, *args, **kwargs):
            if cls.instance is None:
                print('creating a new instance')
                cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
            else:
                print('warning: only one instance allowed')
            return cls.instance
    class MySingleton(metaclass=Singleton):
        pass
    

    实例化

    >>> a = MySingleton()
    creating a new instance
    >>> b = MySingleton()
    warning: only one instance allowed
    >>> c = MySingleton()
    warning: only one instance allowed
    

    元类的应用场景2: 创建APIs

    (2022.03.16 Wed)

    >>> from django.db import models
    >>> class Vehicle(models.Model):
           color = models.CharField(max_length=10)
           wheels = models.IntegerField()
    

    接下来可以实例化Vehicle这个类

    >>> car = Vehicle(color="Blue", wheels=4)
    >>> car.wheels
    4
    

    元类的应用,比如Django ORM,Flask,SQLAlchemy和AOP等。

    类在创建时到底发生了什么

    (2022.02.25 Fri)
    Python程序的三个基础block分别是

    • Statements
    • Functions
    • Classes

    类的命名空间被保存成字典

    class demo:
        var1 = 1
        def __init__(self):
            self.value = 100
    >>> demo.__dict__
    mappingproxy({'__dict__': <attribute '__dict__' of 'demo' objects>,
                  '__doc__': None,
                  '__init__': <function demo.__init__ at 0x10f3db1f0>,
                  '__module__': '__main__',
                  '__weakref__': <attribute '__weakref__' of 'demo' objects>,
                  'var1': 1})
    >>> a = demo()
    >>> a.__dict__
    {'value': 100}
    

    当一个类被创建的时候,发生了如下几步

    • 类的本体被隔离 The body (statements and methods) of the class is isolated.
    • 类的命名空间字典被创建,但不赋值 The namespace dictionary of the class is created, not populated though.
    • 执行类的本体,类命名空间字典被赋值 The body of the class executes, then the namespace dictionary is populated with all of the attributes, methods defined, and some additional useful info about the class.
    • 元类在基类中被标记出 The metaclass is identified in the base classes or the metaclass hooks (explained later) of the class to be created.
    • 用类名和属性值实例化元类 The metaclass is then called with the name, bases, and attributes of the class to instantiate it.

    装饰器Decorator

    (2022.02.10 Thur)
    参考Python装饰器

    类装饰器Class decorator

    (2022.02.25 Fri)
    参考Python装饰器

    Reference

    1 https://developer点ibm点com/tutorials/ba-metaprogramming-python/
    2 realpython com primer-on-python-decorators (https冒号//realpython点com/primer-on-python-decorators/)
    3 编写高质量代码 改善Python编程的91个建议,张颖等著,机械工业出版社

    相关文章

      网友评论

          本文标题:Python类-元编程Meta programming, sin

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