zoukankan      html  css  js  c++  java
  • Python开发基础----反射、面向对象进阶

    isinstance(obj,cls)和issubclass(sub,super)

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象,如果是返回True

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

    issubclass(sub, super)检查sub类是否是 super 类的派生类,如果是返回True

    1 class Foo(object):
    2     pass 
    3 class Bar(Foo):
    4     pass
    5 issubclass(Bar, Foo)

    反射

    反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。

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

    示例代码:

    1 class Teacher:
    2     school='jialidun'
    3     def __init__(self,name,age):
    4         self.name=name
    5         self.age=age
    6     def teach(self):
    7         print('%s teach' %self.name)

    通过字符串的方式判断是否存在一个属性:

    1 t=Teacher('bob',18)
    2 print(hasattr(Teacher,'name'))  #False
    3 print(hasattr(Teacher,'school'))    #True
    4 print(hasattr(Teacher,'teach'))     #True
    5 print(hasattr(t,'name'))  #True
    6 print(hasattr(t,'school'))    #True
    7 print(hasattr(t,'teach'))     #True

    通过字符串的方式获取一个属性:

    1 print(getattr(Teacher,'school'))    #获取到则返回属性的值
    2 print(getattr(Teacher,'sdfad',None))    #获取不到返回None,如果不指定None那么抛出异常错误

    通过字符串的方式设定一个属性:

    1 setattr(Teacher,'sex','male')    #设定Teacher类的属性sex='male'
    2 setattr(t,'sex','female')    #设定对象t对象的属性sex='female'
    3 print(Teacher.__dict__)
    4 print(t.__dict__)

    通过字符串的方式删除一个属性:

    1 delattr(Teacher,'sex')
    2 delattr(t,'sex')

    反射应用场景:用户交互

     1 class Cmd:
     2     def __init__(self,name):
     3         self.name=name
     4     def run(self):
     5         while True:
     6             cmd=input('>>>').strip()
     7             if not cmd:continue
     8             if hasattr(self,cmd):    #判断这个类包含不包含输入的属性
     9                 func=getattr(self,cmd)    #如果包含,获取该属性
    10                 func()    #执行该属性(输入name会抛错提示字符串不能被调用,因为name是一个数据属性,而非函数属性)
    11             else:
    12                 print('not valid func')
    13     def ls(self):
    14         print('ls function')
    15     def pwd(self):
    16         print('pwd function')
    17     def cat(self):
    18         print('cat function')
    19 c=Cmd('bob')
    20 c.run()

    反射的好处

    实现可插拔机制:可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,即可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能

    动态导入模块:基于反射当前模块成员

    __str__方法

    改变对象的字符串显示

     1 class Teacher:
     2     def __init__(self,name,age):
     3         self.name=name
     4         self.age=age
     5 t=Teacher('bob',18)
     6 print(t)
     7 输出结果
     8 <__main__.Teacher object at 0x0000020FC4DA9278>
     9 
    10 #########分割线君###########
    11 
    12 class Teacher:
    13     def __init__(self,name,age):
    14         self.name=name
    15         self.age=age
    16     def __str__(self):
    17         return '<name:%s age:%s>' % (self.name, self.age)
    18 t=Teacher('bob',18)
    19 print(t)    #t.__str__()
    20 输出结果:类中的__str__函数的执行结果
    21 <name:bob age:18>

    __del__方法

    在程序执行完了之后会自动执行的内容

     1 class Foo:
     2     def __init__(self,x):
     3         self.x=x
     4     def __del__(self):
     5         print('执行__del__')
     6         '''一般用来做一些关于对象执行完了之后剩下的垃圾的清理操作'''
     7 f=Foo(10)
     8 print('执行完了')
     9 
    10 输出结果:先执行最后的print,没有代码了执行__del__函数
    11 执行完了
    12 执行__del__

    删除对象后立即执行的内容

     1 class Foo:
     2     def __init__(self,x):
     3         self.x=x
     4     def __del__(self):
     5         print('执行__del__')
     6         '''做一些关于对象的清理操作'''
     7 f=Foo(10)
     8 del f     #删除的时候也会执行del内容
     9 print('执行完了')
    10 
    11 输出结果:删除了f对象后执行了__del__后才执行最后的print
    12 执行__del__
    13 执行完了

    item系列

    以中括号的方式进行处理类似于:

    1 l=['a','b','c']
    2 dic={'a':1}
    3 print(l[1])
    4 print(dic['a'])

    __getitem__、__setitem__、__delitem__

     1 class Teacher:
     2     def __init__(self,name,age,sex):
     3         self.name=name
     4         self.age=age
     5         self.sex=sex
     6     def __getitem__(self, item):    #查询
     7         # return getattr(self,item)
     8         return self.__dict__[item]
     9     def __setitem__(self, key, value):    #设置
    10         # setattr(self,key,value)
    11         self.__dict__[key]=value
    12     def __delitem__(self, key):    #删除
    13         # delattr(self,key)
    14         self.__dict__.pop(key)
    15 f=Teacher('bob',18,'male')
    16 print(f.name) #f['name']
    17 print(f['name'])    #查询
    18 f['name']='bob_nb'    #设置
    19 print(f.__dict__)
    20 del f['name']    #删除
    21 print(f.__dict__)

    __len__方法

    给对象提供len()统计方法

    1 class Teacher:
    2     def __init__(self,name,age,sex):
    3         self.name=name
    4         self.age=age
    5         self.sex=sex
    6     def __len__(self):    #长度设置为10
    7         return 10
    8 f=Teacher('bob',18,'male')
    9 print(len(f))    #输出10

    其他方法(补充)

    __setattr__,__delattr__,__getattr__方法

     1 class Foo:
     2     x=1
     3     def __init__(self,y):
     4         self.y=y
     5     def __getattr__(self, item):
     6         print('----> from getattr:你找的属性不存在')
     7     def __setattr__(self, key, value):  #限制赋值,无法对属性直接赋值,必须要对__dict__进行操作赋值
     8         print('----> from setattr')
     9         # self.key=value #这就无限递归了,任何赋值操作都会调用__setattr__的运行,所以....
    10         # self.__dict__[key]=value #应该使用这种方式,操作字典可以赋值成功
    11     def __delattr__(self, item):
    12         print('----> from delattr')
    13         # del self.item #无限递归了,同__setattr__方法的无限递归
    14         self.__dict__.pop(item)
    15 #__setattr__添加/修改属性会触发它的执行
    16 f1=Foo(10)
    17 f1.__setattr__('a',1)   #不是直接操作字典,无法赋值
    18 print(f1.__dict__) # 因为重写了__setattr__,凡是赋值操作都会触发它的运行,什么都不写,就是根本没赋值,除非直接操作属性字典,否则永远无法赋值
    19 f1.z=3
    20 print(f1.__dict__)
    21 #__delattr__删除属性的时候会触发
    22 f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
    23 del f1.a    #删除的时候如果上面函数是del self.item,会无限递归
    24 print(f1.__dict__)
    25 
    26 #__getattr__只有在使用点调用属性且属性不存在的时候才会触发
    27 f1.xxxxxx

    包装(对标准数据类型进行方法修改)

    通过继承和派生的方式,进行修改源生数据类型的方法

     1 class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
     2     def append(self, p_object):
     3         '派生自己的append:加上类型检查'
     4         if not isinstance(p_object,int):
     5             raise TypeError('must be int')
     6         super().append(p_object)
     7     @property
     8     def mid(self):
     9         '新增自己的属性'
    10         index=len(self)//2
    11         return self[index]
  • 相关阅读:
    思念
    空白
    curl json string with variable All In One
    virtual scroll list All In One
    corejs & RegExp error All In One
    socket.io All In One
    vue camelCase vs PascalCase vs kebabcase All In One
    element ui 表单校验,非必填字段校验 All In One
    github 定时任务 UTC 时间不准确 bug All In One
    input range & color picker All In One
  • 原文地址:https://www.cnblogs.com/chenqizhou/p/7200905.html
Copyright © 2011-2022 走看看