zoukankan      html  css  js  c++  java
  • 反射

    一.反射

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象

    1 class Foo(object):
    2     pass
    3  
    4 obj = Foo()
    5  
    6 isinstance(obj, Foo)

    issubclass(sub, super)检查sub类是否是 super 类的派生类

     1 class Bar():
     2     pass
     3 class Foo(Bar):
     4     pass
     5 obj=Foo()
     6 print(Foo.__bases__)   #判断是不是继承类
     7 print(issubclass(Foo,Bar))
     8 
     9 
    10 
    11 
    12 (<class '__main__.Bar'>,)
    13 True

    1.什么是反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

     2.python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    hasattr(object,name)

      1.文件直接运行,把一个文件当成脚本运行

      2.当成模块导入

     1 class People:
     2     country='China'
     3     def __init__(self,name):
     4         self.name=name
     5 
     6 p=People('egon')
     7 print(p.__dict__)
     8 People.country    #调的不是字符串
     9 #hasattr
    10 print('name' in p.__dict__)
    11 print(hasattr(p,'name'))
    12 print(hasattr(p,'country'))   #p.country
    13 print(hasattr(People,'country'))  #People.country
    14 print(hasattr(People,'__init__')) #People.__init__
    15 
    16 
    17 {'name': 'egon'}
    18 True
    19 True
    20 True
    21 True
    22 True

    getattr(object,name,default=None)

     1 class People:
     2     country='China'
     3     def __init__(self,name):
     4         self.name=name
     5     def walk(self):
     6         print('%s is walking' %self.name)
     7 
     8 p=People('egon')
     9 
    10 
    11 #getattr
    12 res=getattr(p,'country')  #res=p.country
    13 print(res)
    14 
    15 f=getattr(p,'walk')  #t=p.walk
    16 print(f)
    17 
    18 f1=getattr(People,'walk')  #类的函数属性
    19 print(f1)
    20 
    21 f()   #绑定方法第一个参数不用传
    22 f1(p)  #函数不会自动传值
    23 
    24 China
    25 <bound method People.walk of <__main__.People object at 0x00000000004D1978>>
    26 <function People.walk at 0x00000000004CE2F0>
    27 egon is walking
    28 egon is walking
     1 print(getattr(p,'xxxx','这个属性确实不存在'))  #保证程序不会抛出异常
     2 #或者是用下面这个
     3 
     4 if hasattr(p,'walk'):
     5     func=getattr(p,'walk')
     6     func()
     7 print('=======>')
     8 
     9 
    10 
    11 这个属性确实不存在
    12 egon is walking
    13 =======>
    14 =======>

    setattr(x,y,z)

     1 p.sex='male'
     2 print(p.sex)
     3 print(p.__dict__)
     4 setattr(p,'age',18)
     5 print(p.__dict__)
     6 print(p.age)
     7 print(getattr(p,'age'))
     8 
     9 
    10 
    11 
    12 male
    13 {'sex': 'male', 'name': 'egon'}
    14 {'sex': 'male', 'name': 'egon', 'age': 18}
    15 18
    16 18

    delattr(x,y)

     1 # print(p.__dict__)
     2 # del p.name
     3 # print(p.__dict__)
     4 print(p.__dict__)
     5 delattr(p,'name')
     6 print(p.__dict__)
     7 
     8 
     9 
    10 
    11 {'name': 'egon'}
    12 {}

    3.反射当前模块的属性  

    this_module=sys.modules[__name__]

    import sys
    
    x=11
    class Foo:
        pass
    def s1():
        print('s1')
    
    def s2():
        print('s2')
    
    this_module = sys.modules[__name__]    #获取当前模块
    print(this_module)
    
    print(hasattr(this_module,'s1'))
    print(getattr(this_module,'s2'))
    print(this_module.s2)
    print(this_module.s1)
    
    
    <module '__main__' from 路径
    True
    <function s2 at 0x00000000006BE2F0>
    <function s2 at 0x00000000006BE2F0>
    <function s1 at 0x00000000006BE268>

    4.反射的用途:

    1.把字符串映射成可执行过程

    2.实现可插拔机制

    1 while True:
    2     cmd=input('>>:').strip()
    3     if not cmd:continue
    4     # if cmd in func_dic:
    5     #     func=func_dic.get(cmd) #hasattr
    6     #     func()                 #func=getattr()
    7     if hasattr(this_module,cmd):
    8         func=getattr(this_module,cmd)
    9         func()
    1 class FtpClient:
    2     'ftp客户端,但是还没有实现具体的功能'
    3     def __init__(self,addr):
    4         print('正在连接服务器[%s]' %addr)
    5         self.addr=addr
     1 import ftpclient
     2 #from module import FtpClient
     3 f1=ftpclient.FtpClient('192.168.1.1')
     4 if hasattr(f1,'get'):   #有木有get方法
     5     func_get=getattr(f1,'get')
     6     func_get()
     7 else:
     8     print('---->不存在此方法')
     9     print('处理其他的逻辑')
    10 # print(ftpclient)
    11 # print(ftpclient.FtpClient)
    12 
    13 
    14 
    15 
    16 正在连接服务器[192.168.1.1]
    17 ---->不存在此方法
    18 处理其他的逻辑

    通过字符串导入模块

     1 m=input('请输入你要导入的模块:')
     2 m1=__import__(m)
     3 print(m1)
     4 print(m1.time())
     5 
     6 #推荐使用方法
     7 import importlib
     8 t=importlib.import_module('time')
     9 print(t.time())
    10 
    11 
    12 
    13 请输入你要导入的模块:time
    14 <module 'time' (built-in)>
    15 1493021033.3454628

    手动加上类型限制,弥补python没有类型限制的不足。

     1 class Foo:
     2     def __init__(self,name):
     3         self.name=name
     4 
     5     def __setattr__(self,key,value):  #都是把属性加到字典里的,递归超过最大限制
     6         if not isinstance(value,str):
     7             raise TypeError('must be str')
     8         # print('---setattr---key:%s,value:%s' %(key,value))
     9         #setattr(self,key,value)  #self.key=value 递归了,一直再设置属性 #都是把属性加到字典里的,递归超过最大限制
    10         self.__dict__[key]=value  #使用它
    11 
    12     def __delattr__(self, item):
    13         print('---> from delattr')
    14         self.__dict__.pop(item)
    15 
    16 f1=Foo('egon')
    17 f1.age='18'
    18 print(f1.name)
    19 print(f1.age)
    20 print(f1.__dict__)  ## 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
    21 
    22 f1.__dict__['a']=3
    23 del f1.age
      print(f1.__dict__) ##字典里还有age

     1 class Foo:
     2     def __init__(self,x):
     3         self.name=x
     4     #属性不存在的情况下才会触发
     5     def __getattr__(self, item):
     6         print('getattr-->%s %s' %(item,type(item)))
     7 
     8 f=Foo('egon')
     9 print(f.xxx)
    10 
    11 
    12 
    13 getattr-->xxx <class 'str'>
    14 None     #返回None

    5.二次加工标准类型

    定制自己的数据类型

    定制列表里只加数字

     1 class List(list):    ##继承内置的数据类型
     2     def append(self, p_object):
     3         if not isinstance(p_object,int):
     4             raise TypeError('must be int')
          #self.append(p_object) 作为对比,这个不对的
    5 super().append(p_object) #完成真正的append 6 l=List([1,2,3]) 7 print(l) 8 l.append(4) 9 print(l) 10 11 l.insert(0,-1) 12 l.insert(0,'123') 13 print(l) 14 15 16 [1, 2, 3] 17 [1, 2, 3, 4] 18 ['123', -1, 1, 2, 3, 4]

    规范提示数据类型:

     1 def test(x:int,y:int)->int:
     2     return x+y
     3 print(test.__annotations__)
     4 
     5 print(test(1,2))
     6 # print(test(1,'3'))
     7 
     8 
     9 
    10 
    11 {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
    12 3

    1.使用继承的原理二次加工

     1 class List(list):
     2     def append(self, p_object):
     3         if not isinstance(p_object,int):
     4             raise TypeError('must be int')
     5         #self.append(p_object)
     6         super().append(p_object)
     7     # def insert(self, index, p_object):
     8     #     if not isinstance(p_object,int):
     9     #         raise TypeError('must be int')
    10     #     #self.append(p_object)
    11     #     super().insert(index,p_object)
    12 l=List([1,2,3])
    13 print(l)
    14 l.append(4)
    15 # print(l)
    16 print(l)
    17 l.insert(0,-1)
    18 print(l)
    19 # l.insert(0,'123')
    20 # print(l)
    21 
    22 
    23 [1, 2, 3]
    24 [1, 2, 3, 4]
    25 [-1, 1, 2, 3, 4]

     2.授权的方式实现定制自己的数据类型

    授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。

    实现授权的关键点就是覆盖__getattr__方法

     1 #不能用继承,来实现open函数的功能
     2 # f=open('a.txt','w')
     3 # print(f)
     4 # f.write('111')
     5 import time
     6 class Open:
     7     def __init__(self,filepath,m='r',encode='utf-8'):
     8         self.x=open(filepath,mode=m,encoding=encode)
     9         self.filepath=filepath
    10         self.mode=m
    11         self.encoding=encode
    12     def write(self,line):
    13         print('f自己的write',line)
    14         t=time.strftime('%Y-%m-%d %X')
    15         self.x.write('%s %s'%(t,line))
    16 
    17 f=Open('b.txt','w')
    18 print(f)
    19 f.write('1111
    ')
    20 f.write('11111
    ')
    21 f.write('11111
    ')
    22 f.write('11111
    ')
    import time
    class Open:
        def __init__(self,filepath,m='r',encode='utf-8'):
            self.x=open(filepath,mode=m,encoding=encode)
            self.filepath=filepath
            self.mode=m
            self.encoding=encode
        def write(self,line):
            print('f自己的write',line)
            t=time.strftime('%Y-%m-%d %X')
            self.x.write('%s %s'%(t,line))
    
        def __getattr__(self, item):
            print('=------>',item,type(item))
            return (getattr(self.x,item))
    
    # f=Open('b.txt','w')
    # print(f)
    # f.write('1111
    ')
    # f.write('11111
    ')
    # f.write('11111
    ')
    # f.write('11111
    ')
    
    f=Open('b.txt','r+')
    print(f.read)
    
    res=f.read()  #self.x.read()
    print(res)
    print('=-==>',f.read())
    f.seek(0)
    print(f.read())
    # f.flush()
    # f.close()
    
    
    =------> read <class 'str'>
    <built-in method read of _io.TextIOWrapper object at 0x00000000008EEA68>
    =------> read <class 'str'>
    2017-04-24 17:49:50 1111
    2017-04-24 17:49:50 11111
    2017-04-24 17:49:50 11111
    2017-04-24 17:49:50 11111
    
    =------> read <class 'str'>
    =-==> 
    =------> seek <class 'str'>
    =------> read <class 'str'>
    2017-04-24 17:49:50 1111
    2017-04-24 17:49:50 11111
    2017-04-24 17:49:50 11111
    2017-04-24 17:49:50 11111

    模拟open()打开文件

    import time
    class Open():
        def __init__(self,filepath):
            self.path=filepath
            self.x=open(filepath,'w+')
        def write(self,value):
            t=time.strftime('%Y-%m-%d')
            self.x.write(t+value)
        def __getattr__(self, item):
            if hasattr(self.x,item):
                return getattr(self.x,item)
    
    f=Open('a.txt')
    f.read()
    f.seek(0)
    f.flush()
  • 相关阅读:
    flock对文件锁定读写操作的问题 简单
    hdu 2899 Strange Fuction(二分)
    hdu 2199 Can you solve this equation? (二分)
    poj 3080 Blue Jeans (KMP)
    poj 2823 Sliding Window (单调队列)
    poj 2001 Shortest Prefixes (trie)
    poj 2503 Babelfish (trie)
    poj 1936 All in All
    hdu 3507 Print Article (DP, Monotone Queue)
    fzu 1894 志愿者选拔 (单调队列)
  • 原文地址:https://www.cnblogs.com/jiangshitong/p/6758323.html
Copyright © 2011-2022 走看看