python的反射与元类

 # 一,面向对象的内置函数
class Foo:
    pass
obj=Foo()

print(isinstance(obj,Foo))
print(isinstance(Foo,type))# Ture
#isinstance()判断是否是对象,第一个参数为对象,第二个为类

# 在python3中统一类与类型的概念
d={'x':1}  #d=dict({'x':1})

print(type(d) is dict)
print(isinstance(d,dict))#Ture

# issubclass()

class Parent:
    pass

class Sub(Parent):
    pass

print(issubclass(Sub,Parent))

print(issubclass(Parent,object))#Ture

# 二。反射
#  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'))
# print(hasattr(peo1,'uu'))#False
#
# print(getattr(peo1,'name'))#得到一个值egon
# print(getattr(People,'xou',None))#如果找不到该属性,第三个参数如果写则不报错,并且返回该参数,结果为None
#
# setattr(peo1,'country','China')  #peo1.country='China'
# print(peo1.country)
#
# print(peo1.__dict__)
# delattr(peo1,'name')#del peo1.name 删除属性name
# print(peo1.__dict__)

class Ftp:
    def __init__(self,ip,port):
        self.ip=ip
        self.port=self

    def get(self):
        print('GET function')

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

    def run(self):
        while True:
            choice=input('输入你要操作的命令:').strip()
            # if hasattr(self,choice):
            #     m=getattr(self,choice,None)
            #     m()
            m=getattr(self,choice,None)#拿到输入的值,因为是字符串,
            if m:
                m()
            else:
                print('打印命令不存在')#找到属性则运行,就是反射


obj1=Ftp('11.4..5..6',222)
obj1.run()
 
# 三。内置方法定值类的功能
#  1、__str__ 的方法
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)

obj1=People('egon',18)
obj2=People('alex',19)
print(obj1) #obj.__str__()  name:egon age:18
print(obj2) #obj.__str__()  name:alex age:19

d={'x':1} #d=dict({'x':1})
print(d)
#对象和d一样可以直接的打印

# 2.__del__ 析构方法
#
# __del__会在对象被删除之前自动触发
class People:
    def __init__(self,name,age):
        self.name=name
        self.age=age
        self.f=open('a.txt','rt',encoding='utf-8')

    def __del__(self):

        self.f.close()
        #做回收系统资源相关的事情

obj=People('egon',18)

print('打印')
# obj在运行完就回收

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

    class Foo: #Foo=元类()
      pass

2.为何要用元类
   元类是负责产生类的,所以我们学习元类或者自定义元类的目的
   是为了控制类的产生过程,还可以控制对象的产生过程

3、如何用元类

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

# cmd="""
# x=1
# def func(self):
#     pass
# """
# class_dic={}
# exec(cmd,{},class_dic)
#
# print(class_dic)
#造出类的名称空间 {'x': 1, 'func': <function func at 0x000000E4D57E1E18>}

#2.创建类的方法有两种
# 大前提:如果说类也是对象的话,那么用class关键字去创建类的过程也是一个实例化的过程
# 该实例化的目的是为了得到一个类,调用的是元类
#
# 2.1 方式一;用默认的元类type
# class People: #People=type(....)
#     country='china'
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#
#     def eat(self):
#         print('%s is eating '%self.name)
#
# print(type(People))
#
# # 2.1.1 创建类的三要素:类名,基类,类的名称空间
# 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)
#
# # People=type(类名,基类,类的名称空间)
# People1=type(class_name,class_bases,class_dic)
# print(People1)
# obj1=People1('egon',18)
# print(People)
# obj=People('egon',18)
#
# obj1.eat()
# obj.eat()
#
# 2.2 方式二:用的自定义的元素
# 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=(object,)
# 3. 执行类体代码,拿到一个类的名称空间class_dic{....}
# 4. 调用People=type(class_name,class_bases,class_dic)
# class People(object,metaclass=Mymeta):#People=Mymeta(类名,基类们,类的名称空间)
#     country='China'
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#
#     def eat(self):
#         print('%s is eating '%self.name)
#
# # 应用:自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程
# class Mymeta(type):#只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
#     def __init__(self,class_name,class_bases,class_dic):
#         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_name,class_dic)#重用父类的功能
#
# class People(object,metaclass=Mymeta):#People=Mymeta('People',(object,),{..})
#     '''这是People类'''
#     country='china'
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#
#     def eat(self):
#         print('%s is eating '%self.name)
#
# # 3 储备知识:__call__
# class Foo:
#     def __call__(self, *args, **kwargs):
#         print(self)
#         print(args)
#         print(kwargs)
# obj=Foo()
#
# # 要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个__call__方法
# # 该方法会在调用对象的时候自动触发
# obj(1,2,3,x=1)#给函数类传值

# 4、自定义元类来控制类的调用的过程,即类的实例化过程
class Mymeta(type):

    def __call__(self, *args, **kwargs):
        # print(self)#self是People
        # print(args)
        # print(kwargs)
        # return 123

    #1.先造出一个People的空对象
        obj=self.__new__(self)
    # 2.为该空对象初始化独有的属性
    #     print(args,kwargs)
        self.__init__(obj,*args,**kwargs)

    # 3.返回一个初始化对象
        return obj

class People(object,metaclass=Mymeta):
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat(self):
        print('%s is eating'%self.name)

    def __new__(cls, *args, **kwargs):
        print(cls)
        #cls.__new__(cls) 错误
        obj=super(People,cls).__new__(cls)
        return obj

#分析:调用People的目的

# 1.先造出一个People的空对象
# 2、为该对空对象初始化独有的属性
obj1=People('egon1',age=18)
obj2=People('egon2',age=18)

print(obj1)
print(obj2)

obj=People('egon',age=18)

print(obj.__dict__)

print(obj.name)

obj.eat()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值