zoukankan      html  css  js  c++  java
  • python中的元类以及反射

    一,元类

    元类也是类,它是用来创建类的类

    在默认情况下所有元类都是type

    只要是继承了type 那么这个类就变成了一个元类。

    自定义元类:

    class MyType(type):
        def __init__(self,clss_name,bases,dict):
            super().__init__(clss_name,bases,dict)
            print(clss_name,bases,dict)
            if not clss_name.istitle():
                raise Exception("你丫的 类名不会写...")
    
    # 为pig类指定了元类为MyType
    class Pig(metaclass=MyType):
        pass
    
    class Duck(metaclass=MyType):
        pass

    二,元类中的call方法:

    当你调用类对象时会自动执行元类中的__call__方法,并将这个类本身作为第一个参数传入。
    覆盖元类中的call之后,这个类就无法产生对象,必须用super().__call__ 来完成对象创建,而且还要返回值

    使用场景:

    当想要控制对象的创建过程时,就会覆盖call方法。

    当想要控制类的创建过程时,就会覆盖init 方法。

    实现将对象的所有属性名称转为大写:4

    lass MyType(type):
        def __call__(self, *args, **kwargs):
            new_args = []
            for a in args:
                new_args.append(a.upper())
    
            print(new_args)
            print(kwargs)
            return super().__call__(*new_args,**kwargs)
    
    
    class Person(metaclass=MyType):
        def __init__(self,name,gender):
            self.name = name
            self.gender = gender
    
    p = Person(name="jack",gender="woman")
    print(p.name)
    print(p.gender)

    2.new 方法

    当创建类对象时,会首先执行元类中的__new__方法,并拿到一个空对象,然后会自动调用__init__

    初始化方法。

    如果覆盖了这个方法,那new方法必须要有返回值,而且返回值必须是类对象

    class Meta(type):
    
        def __new__(cls, *args, **kwargs):
            print(cls) # 元类自己
            print(args) # 创建类需要的几个参数  类名,基类,名称空间
            print(kwargs) #空的 
            print("new run")
            # return super().__new__(cls,*args,**kwargs)
            obj = type.__new__(cls,*args,**kwargs)
            return obj
        def __init__(self,a,b,c):
            super().__init__(a,b,c)
            print("init run")
    class A(metaclass=Meta):
        pass
    print(A)

    3.单例:

    指的是一个类产生一个对象

    单例是为了节省资源,当一个类的所有对象属性全部相同时,就没必要创建多个对象

    元类实现:

    # 单例n元类
    class Single(type):
    def __call__(self, *args, **kwargs):
    if hasattr(self,"obj"): #判断是否存在已经有的对象
    return getattr(self,"obj") # 有就返回

    obj = super().__call__(*args,**kwargs) # 没有则创建
    print("new 了")
    self.obj = obj # 并存入类中
    return obj


    class Student(metaclass=Single):
    def __init__(self,name):
    self.name = name


    class Person(metaclass=Single):
    pass

    # 只会创建一个对象
    Person()
    Person()

    三,反射

    反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力

    反射其实就是通过字符串操作属性

    1.hasattr:判断某个对象的某个属性是否存在

    2.getattr:从某个对象中取出某个属性

    3.setattr:给某个对象添加某个属性

    4.delattr:从某个对象中删除某个属性

  • 相关阅读:
    如果拷贝项目出现各种找不到文件的时候,基本就是没有标记,或者文件名的问题,Could not find resource mybatis.xml,解决方法
    The error may exist in com/bjpowernode/dao/StudentDao.xml ### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderExcept
    一个简单jpa例子
    @PathVariable
    java.lang.NoClassDefFoundError: org/apache/log4j/Priority的问题解决
    yml中driver-class-name: com.mysql.jdbc.Driver 解析不到的问题
    docker 操作镜像的基本操作
    Navicat 远程连接Docker容器中的mysql 报错:1251
    spring boot中常用的配置文件的重写
    MVC最全jar包
  • 原文地址:https://www.cnblogs.com/wujc3/p/11272430.html
Copyright © 2011-2022 走看看