面向对象高级
Posted cs2612109
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象高级相关的知识,希望对你有一定的参考价值。
在介绍反射之前,先来介绍两个关于类的内置方法,第一个是用来判断对象是否是某一类的对象(以前常说的判断是否是某一类型,类与类型其实是一个概念),第二个则是用来判断某一类是否是继承了另一个类
l=list([1,2,3])
print(isinstance(l,list)) #True
class People:
def __init__(self):
pass
class Chinese(People):
def __init__(self):
pass
print(issubclass(Chinese,People))#True
#两者用法一致,均是将判断的对象与对象可能是某一类型作为第一第二参数传入
2.反射(反省)
先来给反射下一个定义:反射就是通过字符串来操作python代码中的变量,函数,甚至类与方法,(如何去理解这句话呢,试想我们如果想让打印机打印,是不是要给它一个打印的指令呢,现在如果说你必须通过输入的形式去直接命令计算机,让计算机能理解你输入的字符串到底是对应什么操作,关键在于我们提供input输入的都是字符串,而计算机是无法直接识别字符串的),那就要介绍反射中的四小龙了,
1.hasattr 判断一个变量是否能够加点调用一个名字,返回值为True 或 False
class Foo:
x=1
def __init__(self):
pass
def tell(self):
print(‘from tell‘)
print(hasattr(Foo,‘x‘))
2.getattr 直接获取一个变量中的名字的值
class Foo:
x=1
def __init__(self):
pass
def tell(self):
print(‘from tell‘)
obj=Foo()
getattr(obj,‘tell‘)() #from tell
3.setattr
class Foo:
x=1
def __init__(self):
pass
def tell(self):
print(‘from tell‘)
obj=Foo()
print(Foo.x) #1
setattr(Foo,‘x‘,11)
print(Foo.x)#11
4.delattr
class Foo:
x=1
def __init__(self):
pass
def tell(self):
print(‘from tell‘)
obj=Foo()
print(Foo.x) #1
delattr(Foo,‘x‘)
print(Foo.x) #AttributeError: type object ‘Foo‘ has no attribute ‘x‘
总结:上面这四个方法需要注意的地方有以下几点:1.括号里面的传入的前后参数之间,肯定是可以加点再加名字的形式调用(也就是说,只要是设计到通过点加名字就可以调用的形式,都可以转化成上面这四种方式去操作,比如:导入模块后应用模块中的名字,类中属性方法的调用等),2.传入的参数中要寻找的参数必须是以字符串的形式的传入,咋一看好像这种方式更加复杂,但是恰恰相反,请看例子
class People:
country=‘China‘
def __init__(self,name):
self.name=name
def tell(self):
print(‘from tell‘)
def check(self):
print(‘from check‘)
p1=People(‘jby‘)
cmd=input(‘please input your cmd‘).strip()
if hasattr(p1,cmd):
getattr(p1,cmd)()
这样我们就可以直接将用户输入的字符串直接反射到对应的名字身上,从而直接调用~
3.类的内置方法补充
__ str __
__ del __
__ call __(调用)
exec(),eval()
1.str 在对象,在遇到被打印的情况下,自动触发~
class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def __str__(self):#__str__内置方法,遇到print自动触发返回字符串格式类型的数据(可自己定制)
return ‘<name:%s,age:%s,sex:%s>‘%(self.name,self.age,self.sex)
l=list([1,2,3])#用list类产生的对象为什么在打印的时候会直接打印对象里面包含的所有值而不是内存地址原因就是内部有__str__方法
print(l)
p1=People(‘alex‘,73,‘male‘)
print(p1)
2.del 在对象被删除的情况下(在对象被删除之前)自动触发(这里的删除可以是主动删除也可能是程序执行完毕,回收资源删除)
class Myopen:
def __init__(self,filename,mode=‘r‘,encoding=‘utf-8‘):
self.filename=filename
self.mode=mode
self.encoding=encoding
self.f=open(filename,mode=mode,encoding=encoding)
#这里的open申请了系统资源,在程序关闭时应用程序会回收自己资源,但是系统资源没有被回收
def __str__(self):
return ‘%s‘%self.f.read()
def __del__(self):
#这里的__del__会在对象被删除之前(被系统回收),执行将系统资源先回收了
#所有__del__主要用于设计到回收资源这块的应用
print(‘正在删除系统资源‘)
self.f.close()
file=Myopen(‘settings.py‘)
print(file)
3.call 在对象被调用的情况下,自动触发
class Foo:
def __init__(self):
pass
def __str__(self):
return ‘aaa‘
def __del__(self):
pass
def __call__(self, *args, **kwargs):#(调用对象时就会自动触发此方法的执行将对象当作第一个参数传给self,将对象括号内的参数传给args和kwargs)
print(‘执行了__call__‘,args,kwargs)
?
obj=Foo()
obj(1,2,3,a=2,b=3,c=1)#执行了__call__ (1, 2, 3) {‘a‘: 2, ‘b‘: 3, ‘c‘: 1}
4.exec
globalsdic = {}
localsdic = {}
?
exec("""
aaaaaaaaaaaaaaaaaaaa = 1
bbbbbbbbbbbbbbbbbbbbbbbbbbbb = 2
def func1():
print("我是func1")
""",globalsdic,localsdic)
?
?
# 如果同时制定了 全局和局部 则 会字符串中包含名称 解析后存到局部中
# print(globalsdic)
print(localsdic)
localsdic["func1"]()
exec(‘xxxxx‘,{},{})有三个参数第二个是全局名称空间,第三个是局部名称空间,只要没使用global定义,就默认存放在局部名称空间
区别:
exec():其作用 是帮你解析执行python代码 并且将得到的名称 存储到制定的名称空间
eval():计算指定表达式的值。也就是说它要执行的python代码只能是单个表达式**(注意eval不支持任何形式的赋值操作),而不能是复杂的代码逻辑
以上是关于面向对象高级的主要内容,如果未能解决你的问题,请参考以下文章