• python基础之反射内置方法元类


    补充内置函数

    isinstance(obj,Foo)   # 判断obj是不是foo的实例

    issubclass()      # 判断一个类是不是另一个类的子类

    反射

             什么是反射?

                      通过字符串来操作类或者对象的属性

             怎么用?

                      hasattr(adj,’xxx’) 判断adj有没有’xxx’属性

                      getattr(adj,’xxx’,None) adj有’xxx’就返回adj.xxx,没有则返回None,若不指定第三个                                 参数,没有则会报错

                      setattr(adj,’age’,18) adj.age = 18

                      delattr(adj,’age’) def adj.age

    内置方法

           def __str__(self):在对象被打印时,自动触发,应该在该方法内采集与对象有关的信息并return,当print(adj)是会打印__str__(self)中的return值

             def __del__(self) 析构方法,对象被删之前自动触发

    元类

             什么是元类?

                      python中一切皆对象,用class定义的类本身也是一个对象,负责产生该类对象的类称为元类

             为何用元类?

                      元类可以负责产生类,进而控制类的产生还可以控制对象的产生

             如何用元类?

                      ①储备知识:

                      exec()

                      参数一:字符串形式的命令

                      参数二:全局作用域(字典形式),如果不指定,默认为globals()

                      参数三:局部作用域(字典形式),如果不指定,默认为locals()

                               可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中

    创建类的三个要素:类名,父类,类的名称空间
    #类名
    class_name='Chinese'
    #类的父类
    class_bases=(object,)
    #类的名称空间
    class_dic = {}
    #类体
    class_body="""
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def talk(self):
        print('%s is talking' %self.name)
    """
    exec(class_body,{},class_dic)
    People = type(class_name,class_bases,class_dic)  # 实例化类

    class运行原理:

    1.拿到一个字符串形式的类名

    2.拿到类的基类们

    3.执行类体代码,拿到类的名称空间

    4.调用type()再赋值给变量名

     

    应用:自定义元类控制类的产生过程,其实就是调用元类的过程 

    #如果说People=type(类名,类的父类们,类的名称空间),那么我们定义元类如下,来控制类的创建
    class Mymeta(type):  # 继承默认元类的一堆属性
        def __init__(self, class_name, class_bases, class_dic):
            if '__doc__' not in class_dic or not class_dic.get('__doc__').strip():
                raise TypeError('必须为类指定文档注释')
    
            if not class_name.istitle():
                raise TypeError('类名首字母必须大写')
    
            super(Mymeta, self).__init__(class_name, class_bases, class_dic)
    
    
    class People(object, metaclass=Mymeta):
        country = 'China'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def talk(self):
            print('%s is talking' % self.name)
    
    
    #自定义元类,控制类的调用(即实例化)的过程
    class Mymeta(type): #继承默认元类的一堆属性
        def __init__(self,class_name,class_bases,class_dic):
            if not class_name.istitle():
                raise TypeError('类名首字母必须大写')
    
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    
        def __call__(self, *args, **kwargs):
            #self=People
            print(self,args,kwargs) #<class '__main__.People'> ('egon', 18) {}
    
            #1、实例化People,产生空对象obj
            obj=object.__new__(self)
    
            #2、调用People下的函数__init__,初始化obj
            self.__init__(obj,*args,**kwargs)
    
            #3、返回初始化好了的obj
            return obj
    
    class People(object,metaclass=Mymeta):
        country='China'
    
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def talk(self):
            print('%s is talking' %self.name)
    
    obj=People('egon',18)
    print(obj.__dict__) #{'name': 'egon', 'age': 18}
  • 相关阅读:
    洛谷5495:Dirichlet前缀和
    SP5971 LCMSUM
    洛谷1829:crash的数字表格
    洛谷3172:选数
    Codeforces 1295 D. Same GCDs
    洛谷3768:简单的数学题
    NTT学习笔记
    洛谷1169:棋盘制作(悬线法)
    洛谷2444:病毒
    后缀自动机
  • 原文地址:https://www.cnblogs.com/luck-L/p/9244953.html
Copyright © 2020-2023  润新知