• python3 元类编程的一个例子


    【引子】

      虽然我们可以通过“class”语句来定义“类”,但是要想更加细粒度的控制“类”的创建,要使用元类编程才能实现。

      比如说我们要实现这样的一个约束、所有项目中用到的类都应该要为它定义的方法提供文档字符字符串。有两条可行

      的路径 1):依赖工程师的自觉、自律 让他们在定义每一个方法的时候都为方法增加文档字符串, 2):通过元类来做一些

      控制,如果工程师没有为方法提供文档字符,那么就直接报错,直到工程师为方法提供字符串为止。

    【实现1】

      依赖工程师的自觉、自律为方法增加文档字符串

    class Person(object):
        name = None
        def __init__(self,name):
            self.name=name
    
        def say_hello(self):
            """
            print hello My name is xxx  ...
            """
            print("hello My name is {self.name}".format(self=self))

      我们如何能保证每一个方法都增加了文档字符串呢?我一方面要依靠“自觉”另一方面要依靠“纪律性”,最好要有专门的人来做代码

      审核。

    【实现2】

      通过元类来实现这个约束

      第一步:定义一个元类来审核class

    class DocMeta(type):
        """
        检查方法是否有提供文档字符串
        """
        def __init__(self,name,base,attrs):for key,value in attrs.items():
                if key.startswith('__'):
                    #跳过魔术方法
                    continue
                if not hasattr(value,"__call__"):
                    #跳过字段
                    continue
                #如果能进入到这里、那么一定是方法了、于是检查方法有没有文档字符串.
                if not getattr(value,"__doc__"):
                    #没有文档字符串的情况下就报错
                    raise TypeError("{0} must have a docstring".format(key))
                super().__init__(name,base,attrs)

      

      第二步:定义一个通用的基类、以后所有要实现这一约束的类都继承自它

    class Documented(metaclass=DocMeta):
        pass

       注意这个项的元类是我们刚才定义的“DocMeta”类

      第三步:让项目中的类继承自这个基类

    class Person(Documented):
        name = None
        def __init__(self,name):
            self.name=name
    
        def say_hello(self):
            """
            print hello My name is xxx  ...
            """
            print("hello My name is {self.name}".format(self=self))

      

      第四步:和使用普通的类一样使用Person类

    if __name__=="__main__":
        p = Person("welson")
        p.say_hello() #hello My name is welson

    【总结】

      以上代码由于在say_hello 方法中提供了文档字符串、如果没有提供的话、在创建Person类的时候就会报错了

    Traceback (most recent call last):
      File "main.py", line 31, in <module>
        class Person(Documented):
      File "main.py", line 24, in __init__
        raise TypeError("{0} must have a docstring".format(key))
    TypeError: say_hello must have a docstring

      全部代码如下:

    """
    Python元类编程的一个例子
    """
    
    __version__ = '0.1'
    __author__  = '蒋乐哥哥'
    
    
    class DocMeta(type):
        """
        检查方法是否有提供文档字符串
        """
        def __init__(self,name,base,attrs):
            for key,value in attrs.items():
                if key.startswith('__'):
                    #路过魔术方法
                    continue
                if not hasattr(value,"__call__"):
                    #跳过字段
                    continue
                #如果能进入到这里、那么一定是方法了、于是检查方法有没有文档字符串.
                if not getattr(value,"__doc__"):
                    #没有文档字符串的情况下就报错
                    raise TypeError("{0} must have a docstring".format(key))
                super().__init__(name,base,attrs)
    
    
    class Documented(metaclass=DocMeta):
        pass
    
    class Person(Documented):
        name = None
        def __init__(self,name):
            self.name=name
    
        def say_hello(self):
            """
            print hello My name is xxx  ...
            """
            print("hello My name is {self.name}".format(self=self))
    
    # 在不为方法提供文档字符串的情况下会直接报错
    #class Person(Documented):
    #    name = None
    #    def __init__(self,name):
    #        self.name=name
    #
    #    def say_hello(self):
    #        print("hello My name is {self.name}".format(self=self))
    
    if __name__=="__main__":
        p = Person("welson")
        p.say_hello()

    ----------------------------------------

  • 相关阅读:
    UESTC 913 握手 Havel定理+优先队列
    UESTC 912 树上的距离 --LCA+RMQ+树状数组
    UESTC 901 方老师抢银行 --Tarjan求强连通分量
    UESTC 900 方老师炸弹 --Tarjan求割点及删点后连通分量数
    UESTC 899 方老师和农场 --双连通分量的构造
    UESTC 898 方老师和缘分 --二分图匹配+强连通分量
    ACdream OJ 1099 瑶瑶的第K大 --分治+IO优化
    Codeforces Zepto Code Rush 2014 -C
    Floyd判最小环算法模板
    POJ 1364 King --差分约束第一题
  • 原文地址:https://www.cnblogs.com/JiangLe/p/9304576.html
Copyright © 2020-2023  润新知