zoukankan      html  css  js  c++  java
  • 反射

    什么是反射?
    指的是在程序运行过程中可以"动态(不见棺材不掉泪)"获取对象的信息
    为何要用反射?
    如何实现反射?
    class People:
    	def __init__(self,name,age):
    		self.name=name
    		self.age=age
    
    def say(self):
        print('<%s:%s>' %(self.name,self.age))
    
    obj=People('辣白菜同学',18)
    
    实现反射机制的步骤
    1、先通过多dir:查看出某一个对象下可以.出哪些属性来
    print(dir(obj))
    
    2、可以通过字符串反射到真正的属性上,得到属性值
     print(obj.__dict__[dir(obj)[-2]])
    
    四个内置函数的使用:通过字符串来操作属性值
    1、hasattr()
    # print(hasattr(obj,'name'))
     print(hasattr(obj,'x'))
    
    2、getattr()
    print(getattr(obj,'name'))
    
    3、setattr()
    setattr(obj,'name','EGON') ##### obj.name='EGON'
     print(obj.name)
    
    4、delattr()
    delattr(obj,'name') ##### del obj.name
    print(obj.__dict__)
    
    
     res1=getattr(obj,'say') ##### obj.say
     res2=getattr(People,'say') ##### People.say
     print(res1)
     print(res2)
    
    
     obj=10
     if hasattr(obj,'x'):
         print(getattr(10,'x'))
     else:
         pass
    
     print(getattr(obj,'x',None))
    
    
     if hasattr(obj,'x'):
         setattr(obj,'x',111111111) ##### 10.x=11111
     else:
         pass
    
    
    class Ftp:
    	def put(self):
    		print('正在执行上传功能')
    
    	def get(self):
    		print('正在执行下载功能')
    
    	def interactive(self):
    		method=input(">>>: ").strip() ##### method='put'
    
    		if hasattr(self,method):
    			getattr(self,method)()
    		else:
    			print('输入的指令不存在')
    
    
    obj=Ftp()
    obj.interactive()
    
    1、什么是内置方法?
    定义在类内部,以__开头并以__结果的方法
    特点:会在某种情况下自动触发执行
    2、为何要用内置方法?
    为了定制化我们的类or对象
    3、如何使用内置方法
    str:在打印对象时会自动触发,然后将返回值(必须是字符串类型)当做本次打印的结果输出
     class People:
         def __init__(self, name, age):
             self.name = name
             self.age = age
    
         def __str__(self):
             ##### print('运行了...')
             return "<%s:%s>" %(self.name,self.age)
    
    
     obj = People('辣白菜同学', 18)
    
     ##### print(obj.__str__())
     print(obj)  ##### <'辣白菜同学':18>
    
     ##### obj1=int(10)
     ##### print(obj1)
    
    del:在清理对象时触发,会先执行该方法
    class People:
    	def __init__(self, name, age):
    		self.name = name
    		self.age = age
    		self.x = open('a.txt',mode='w')
    		##### self.x = 占据的是操作系统资源
    
    def __del__(self):
        ##### print('run...')
        ##### 发起系统调用,告诉操作系统回收相关的系统资源
        self.x.close()
    
    obj = People('辣白菜同学', 18)
    
    del obj ##### obj.del()
    print('============>')
    
    一:引入:
    一切都源自于一句话:一切皆为对象
    二:什么是元类?
    元类就是用来实例化产生类的类
    关系:元类---实例化---->类(People)---实例化---->对象(obj)
     class People:
         def __init__(self,name,age):
             self.name=name
             self.age=age
    
         def say(self):
             print('%s:%s' %(self.name,self.name))
    
    
     print(People.__dict__)
     如何得到对象
     obj=调用类()
     obj=People('egon',18)
     print(type(obj))
     如果说类也是对象
     People=调用类(。。。)
    
    查看内置的元类:
    1、type是内置的元类
    2、我们用class关键字定义的所有的类以及内置的类都是由元类type实例化产生
    print(type(People))
    print(type(int))
    三:class关键字创造类People的步骤
    类有三大特征:
    ##### 1、类名
     class_name="People"
    
    ##### 2、类的基类
     class_bases=(object,)
    
    ##### 3、执行类体代码拿到类的名称空间
     class_dic={}
     class_body="""
     def __init__(self,name,age):
         self.name=name
         self.age=age
    
     def say(self):
         print('%s:%s' %(self.name,self.name))
     """
     exec(class_body,{},class_dic)
     ##### print(class_dic)
    
    ##### 4、调用元类
     People=type(class_name,class_bases,class_dic)
    
    四:如何自定义元类来控制类的产生
     class Mymeta(type): ##### 只有继承了type类的类才是元类
         #####            空对象,"People",(),{...}
         def __init__(self,x,y,z):
             print('run22222222222....')
             print(self)
             ##### print(x)
             ##### print(y)
             ##### print(z)
             ##### print(y)
             ##### if not x.istitle():
             #####     raise NameError('类名的首字母必须大写啊!!!')
    
         #####          当前所在的类,调用类时所传入的参数
         def __new__(cls, *args, **kwargs):
             ##### 造Mymeta的对象
             print('run1111111111.....')
             ##### print(cls,args,kwargs)
             ##### return super().__new__(cls,*args, **kwargs)
             return type.__new__(cls,*args, **kwargs)
    
    
     ##### People=Mymeta("People",(object,),{...})
     ##### 调用Mymeta发生三件事,调用Mymeta就是type.__call__
    
    ##### 1、先造一个空对象=>People,调用Mymeta类内的__new__方法
    ##### 2、调用Mymeta这个类内的__init__方法,完成初始化对象的操作
    ##### 3、返回初始化好的对象
     class People(metaclass=Mymeta):
         def __init__(self,name,age):
             self.name=name
             self.age=age
    
         def say(self):
             print('%s:%s' %(self.name,self.name))
    
    ##### 强调:
    ##### 只要是调用类,那么会一次调用
    ##### 1、类内的__new__
    ##### 2、类内的__init__
    五:call
     class Foo:
         def __init__(self,x,y):
             self.x=x
             self.y=y
    
         #####            obj,1,2,3,a=4,b=5,c=6
         def __call__(self,*args,**kwargs):
             print('===>',args,kwargs)
             return 123
    
     obj=Foo(111,222)
     ##### print(obj) ##### obj.__str__
     res=obj(1,2,3,a=4,b=5,c=6) ##### res=obj.__call__()
     print(res)
    
    应用:如果想让一个对象可以加括号调用,需要在该对象的类中添加一个方法__call__
    总结:
    对象()->类内的__call__
    类()->自定义元类内的__call__
    自定义元类()->内置元类__call__
    六:自定义元类控制类的调用=》类的对象的产生
    class Mymeta(type): ##### 只有继承了type类的类才是元类
    def __call__(self, *args, **kwargs):
        ##### 1、Mymeta.__call__函数内会先调用People内的__new__
        people_obj=self.__new__(self)
        ##### 2、Mymeta.__call__函数内会调用People内的__init__
        self.__init__(people_obj,*args, **kwargs)
    
        ##### print('people对象的属性:',people_obj.__dict__)
        people_obj.__dict__['xxxxx']=11111
        ##### 3、Mymeta.__call__函数内会返回一个初始化好的对象
        return people_obj
    
    类的产生
    People=Mymeta()=》type.call=>干了3件事
    1、type.call__函数内会先调用Mymeta内的__new
    2、type.call__函数内会调用Mymeta内的__init
    3、type.__call__函数内会返回一个初始化好的对象
    class People(metaclass=Mymeta):
    	def __init__(self,name,age):
    		self.name=name
    		self.age=age
    
    def say(self):
        print('%s:%s' %(self.name,self.name))
    
    def __new__(cls, *args, **kwargs):
        ##### 产生真正的对象
        return object.__new__(cls)
    
    类的调用
    obj=People('egon',18) =》Mymeta.call=》干了3件事
    1、Mymeta.call__函数内会先调用People内的__new
    2、Mymeta.call__函数内会调用People内的__init
    3、Mymeta.__call__函数内会返回一个初始化好的对象
    obj1=People('egon',18)
    obj2=People('egon',18)
    ##### print(obj)
    print(obj1.__dict__)
    print(obj2.__dict__)
    

    属性查找的原则:对象-》类-》父类
    切记:父类 不是 元类
    class Mymeta(type):
    n=444
    
    def __call__(self, *args, **kwargs): #####self=<class '__main__.StanfordTeacher'>
        obj=self.__new__(self) ##### StanfordTeacher.__new__
        ##### obj=object.__new__(self)
        print(self.__new__ is object.__new__) #####True
        self.__init__(obj,*args,**kwargs)
        return obj
    
    class Bar(object):
    ##### n=333
    
    ##### def __new__(cls, *args, **kwargs):
    #####     print('Bar.__new__')
    pass
    
    class Foo(Bar):
    ##### n=222
    
    ##### def __new__(cls, *args, **kwargs):
    #####     print('Foo.__new__')
    pass
    
    class StanfordTeacher(Foo,metaclass=Mymeta):
    	##### n=111
    
    def __init__(self,name,age):
        self.name=name
        self.age=age
    
    
    obj=StanfordTeacher('lili',18)
    print(obj.__dict__)
     print(obj.n)
     print(StanfordTeacher.n)
  • 相关阅读:
    禁止文本被选中
    计算机的发展史及多道技术
    计算机基础知识
    自我介绍
    工作内容1
    在IT行业中的抄袭事件
    哎呀呀
    查看Oracle版本号的方式
    JAVA项目的基本配置
    Ajax请求返回结果为404问题
  • 原文地址:https://www.cnblogs.com/abldh12/p/15211625.html
Copyright © 2011-2022 走看看