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]
时间: 2024-10-31 20:18:12

Python开发基础----反射、面向对象进阶的相关文章

python(24)- 面向对象进阶

面向对象基础知识: 1.面向对象是一种编程方式,此编程方式的实现是基于对类和对象的使用: 2.类是一个模板,模板中包装了多个‘函数’供使用(可以将多函数中公用的变量封装到对象中): 3.对象,根据模板创建的实例(即:对象),实例用于被包装在类中的函数: 4.面向对象三大特性:封装.继承和多态. 面向对象进阶篇详细介绍python类的成员.成员修饰符和类的特殊成员. 类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存

Python开发基础-Day22反射、面向对象进阶

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 cla

python基础_面向对象进阶

@property装饰器 之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效.我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作.如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问

python开发学习-day07(面向对象之多态、类的方法、反射、新式类and旧式类、socket编程)

s12-20160227-day07 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin

Python基础之面向对象进阶

一.isinstance(obj,cls)和issubclass(sub,super) 1.isinstance(obj,cls)检查obj是否是类 cls 的对象 class A: pass obj = A() #实例化对象obj isinstance(对象名,类名)#语法 print(isinstance(obj,A)) #isinstance函数返回的是布尔值,True,则obj,是A产生的对象 print(isinstance(object,A)) #同上,反之,为不是. -------

学习PYTHON之路, DAY 8 - PYTHON 基础 8 (面向对象进阶)

类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份. 一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 字段定义和使用 由上述代码可以看出[普通字段需要通过对象来访问][静态字段通过类访问],在使用上可以看出普通字段和静态字段的归属是

python自动化开发学习-8 面向对象进阶

---恢复内容开始--- 类的成员(字段,方法,属性) 注意:所有成员中,只有普通字段的内容是保存在对象中.而其他成员都是保存在类中,即无论创建多少个对象,在内存中只保留一份. 1.字段 字段包含:普通字段和静态字段,在使用中有所区别,最本质的区别是内存中保存的位置不同. 普通字段:属于对象 静态字段:属于类, 多个对象共用一个字段,主要用于对象的变量内容都一样的情景. 注意: 静态字段在代码加载的时候就被创建了,而普通字段在类被实例化的时候才会被创建.# 示例代码: class Provinc

Python学习之旅—面向对象进阶知识:类的命名空间,类的组合与继承

前言 上篇博客笔者带领大家初步梳理了Python面向对象的基础知识,本篇博客将专注于解决三个知识点:类的命名空间,类的组合以及面向对象的三大特性之一继承,一起跟随笔者老看看今天的内容吧. 1.类的命名空间 在上一篇博客中,我们提到过对象可以动态添加属性,一起来回忆下昨天的知识点,看如下的代码: class A: pass a = A() a.name = 'alex' print(a.name) 这里我们手动为a对象添加了一个属性name,然后直接打印可以得到a对象的名称.通过这个例子,我们可以

Python开发基础-Day23try异常处理、socket套接字基础1

异常处理 错误 程序里的错误一般分为两种: 1.语法错误,这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正 2.逻辑错误,人为造成的错误,如数据类型错误.调用方法错误等,这些解释器是不会进行检测的,只有在执行的过程中才能抛出的错误 异常 异常是python解释器在运行程序的过程中遇到错误所抛出的信息,如: Python异常种类: 常用异常: 1 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x 2 IOError 输入/输出异