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)
  • 相关阅读:
    HDU4474 Yet Another Multiple Problem BFS搜索
    HDU4473 Exam 数学分析
    2013ACM多校联合(4)
    POJ1273 网络流...
    HDU4472 Count 递推
    POJ1149 PIGS 网络流
    UVA10881 Piotr's Ants 想法题
    javascript js string.Format()收集
    修改 设置 vs.net 网站 调试 设为 起始页
    【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
  • 原文地址:https://www.cnblogs.com/abldh12/p/15211625.html
Copyright © 2011-2022 走看看