反射,元类

Posted yf18767106368

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射,元类相关的知识,希望对你有一定的参考价值。

内置函数

技术分享图片
# class Foo:
#     pass
# obj=Foo
# print(isinstance(obj,Foo))
#在python3中统一类与类型的概念
#d={"x":1}#d=dict({"x":1})

#print(type(d) is dict)
# print(isinstance(d,dict))
isinstance(对象名,类名) 判断是否是实列

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

# class Parent:
#     pass
# class Sub(Parent):
#     pass
# print(issubclass(Sub,Parent))
# print(issubclass(Parent,object))
内置函数

反射

1、什么是反射
通过字符串来操作类或者对象的属性

2、如何用
hasattr
getattr
setattr
delattr

class People:
    country="China"
    def __init__(self,name):
        self.name=name
    def eat(self):
        print("%s is eating" %self.name)

peo1=People("egon")
print(hasattr(peo1,"eat"))#查看peo1有没有eat属性 #属性需要加引号,底层原理就是依次判断从对象空间->子类->父类里面是否存在eat
print(getattr(peo1,"eat"))#在又的情况下,用get拿出peo1中的eat,相当于打印peo1.get
print(getattr(peo1,"XXXX","None"))#在找不到这个属性的时候返回None

setattr(peo1,"age",18)#peo1.age=18 #修改属性
print(peo1.age)
print(peo1.__dict__)
delattr(peo1,"name")#del peo1.name #删除属性
print(peo1.__dict__)
技术分享图片
class Ftp:
    def __init__(self,ip,port):
        self.ip=ip
        self.port=port
    def get(self):
        print("GET function")

    def put(self):
        print("PUT function")

    def run(self):
        while True:
            choice = input(">>:").strip()
            # print(choice,type(choice))
            # if hasattr(self,choice):#self是对象conn,#先判断输入的内容是否存在
            #     method=getattr(self,choice)#存在就获取相应功能
            #     method()#调用
            # else:
            #     print("输入的命令不存在")

            method = getattr(self,choice,None)
            if method is None:
                print("输入的命令不存在")
            else:
                method()
conn=Ftp("1.1.1",23)
conn.run()
反射应用
# __str__方法
# class Foo:
#     pass
# obj=Foo()#与d={"x":1}一样
# print(obj)#与print(d)一样,只是obj打印出来是内存地址,d是肉眼能看见的内容
# class People:
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#      #在对象self被打印时,自动触发,应该是打印该方法内采集与对象相关的信息,然后拼接成字符串返回
#     def __str__(self):
#         return"<name:%s age:%s>" %(self.name,self.age) #必须返回的是字符串
#
# obj = People("egon",18)
# obj1=People("yf",17)
# print(obj)#打印对象时触发__str__
# print(obj1)
#__def__格式分析构建方法
#会在对象被删除之前自动触发,文件关闭操作系统可以用到
class People:
    def __init__(self,name,age):
        self.name=name
        self.age=age
        # self.f=open("a.txt","wt",encoding="utf-8")

    def __del__(self):#程序结束之前自动回收操作系统资源,即文件使用时候用
        print("is")#显示运行标记
        # self.f.close() #达到程序运行结束前回收操作系统资源
obj=People("yf",17)
print(obj)
del obj
print("ting")

1、什么是元类
在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象
负责产生该对象的类称之为元类,即元类可以简称为类的类

class Foo: # Foo=元类() 调用类的类是元类
pass
2、为何要用元类
元类是负责产生类的,所以我们学习元类或者自定义元类的目的
是为了控制类的产生过程,还可以控制对象的产生过程

3、如何用元类

#1、储备知识:内置函数exec的用法

#全局的名称空间 出了内置的名称空间还有文件执行过程中产生的#print(globals())可以查看全局的名称空间内名字
# class_name="People"
# class_bases=(object,)
# class_dic={} #exec运行时会将运行中的产生的名字都丢入岛class_dic的名称空间内,类名称空间
# class_body=""" #exec提取这里面的代码并且运行,模拟python代码的运行过程
# country=‘China‘
# def __init__(self,name,age):
#     self.name=name
#     self.age=age
#
# def eat(self):
#     print(‘%s is eating‘ %self.name)

#类名,全局名称空间,类名称空间
# exec(class_body,{},class_dic)#模拟python代码的运行过程,会将运行中的代码名字都丢入岛class_dic的名称空间内
#exec中间的括号内是代表全局的名称空间,模拟类定义阶段定义名称空降操作,讲类定义是的名字丢入到类的名称空间
# People1=type(class_name,class_bases,class_dic)#元类调用赋值给类
# print(People1)#类

#创建类的方式有两种,一种是用class关键字创建,另一种是自定义元类
# 大前提:如果说类也是对象的化,那么用class关键字的去创建类的过程也是一个实例化的过程
# 该实例化的目的是为了得到一个类,调用的是元类
#默认的元类是type,专门产生类用的 #class People: #People=type(类名,父类,类的名称空间)
#创建类的三大要数,类名,父类,类的名称空间

# class_name=‘People‘ #类名
# class_bases=(object,) #父类,元组显示在名称空间内
# class_dic={}#类的字典
# class_body=""" #类体代码
# country=‘China‘
# def __init__(self,name,age):
#     self.name=name
#     self.age=age
#
# def eat(self):
#     print(‘%s is eating‘ %self.name)
# """
# exec(class_body,{},class_dic)

# 准备好创建类的三要素
# print(class_name) #类名
# print(class_bases) #父类
# print(class_dic) #类名称空间
技术分享图片
#自定义元类
# class Mymeta(type):#不继承type就是一个普通的类
#     def __init__(self,class_name,class_bases,class_dic):
#         print(self)#本体是People
#         print(class_name)
#         print(class_bases)
#         print(class_dic)
#         super(Mymeta,self).__init__(class_name,class_bases,class_dic)#重用父类功能

# 分析用class自定义类的运行原理(而非元类的的运行原理):
#1、拿到一个字符串格式的类名class_name=‘People‘
#2、拿到一个类的基类们class_bases=(obejct,)
#3、执行类体代码,拿到一个类的名称空间class_dic={...}
#4、调用People=type(class_name,class_bases,class_dic)

class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):#将元类的格式写入,self是自己建的类
        if class_dic.get("__doc__") is None or len(class_dic.get("__doc__").strip()) == 0:
            raise TypeError("类中必须又文档注释,并且这档注释不能为空")#控制类的名称空间内容
        if not class_name.istitle():
            raise TypeError("类名首字母必须大写")#控制类的名字情况
        super(Mymeta,self).__init__(class_name,class_bases,class_dic) #讲父类的内容传入方式设置,重用父类功能

class People(object,metaclass=Mymeta):#People=Mymeta(类名,基类们,类的名称空间)#完成类的实例化
#定义类的时候会创造空对象,将空对象连同括号内参数一同传给元类的init内
    """你好,China"""
    country="China"
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat(self):
        print("%s is eating" %self.name)
自定义类

 














以上是关于反射,元类的主要内容,如果未能解决你的问题,请参考以下文章

反射,元类

反射 元类

反射元类 练习

反射与元类

面向对象之 元类 , 反射 , 双下方法

反射 动态导入 元类