面向对象进阶
一.isinstance和issubclass
1.身份运算
print(type(2) == int) #True
print(type(2) is int) #True
2.对象与类之间的关系 isinstance
isinstance(obj,cls)判断obj是否是类 cls 的对象 包括继承的判断
class A:pass
class B(A):pass
b=B()
print(isinstance(b,B)) #True
print(isinstance(b,A)) #True
3.类与类之间的关系 issubclass(A,B)
issubclass(A,B) 判断第一个参数疑似子类,第二个参数疑似父类。第一个必须是子类
class A:pass
class B(A):pass
print(issubclass(B,A)) #Trueer
二、反射
1.反射的定义:通过字符串来操作python代码中的变量,函数甚至方法和类
hasattr 判断某一个 变量 是否能够.调用一个名字,返回True或者False
getattr 直接获取一个变量中的名字的值
setattr 为一个变量增加或者修改一个属性
delattr 删除一个变量中的属性或者方法
2.值=getattr(类名,字符串类型的属性名) 如果第二个参数是不存在的属性名则会报错
hasattr判断属性名是否存在 hasattr常与getattr
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: name="alex" age=18 tag=input("<<<:") if tag=="name":print(A.name) if tag=="age":print(A.age) #利用反射实现上述功能 print(getattr(A,tag)) 2.获取方法 class A: def __init__(self,name,age): self.name=name self.age=age def show(self): for key in self.__dict__: print(key,self.__dict__[key]) alex=A("alex",18) if hasattr(alex,"show"): func=getattr(alex,"show") #得到的是内存地址 func()
3.##setattr设置和修改属性###
class A:
def __init__(self,name):
self.name=name
alex=A("alex")
setattr(alex,'sex',"man") #增加
print(alex.sex)
setattr(alex,'name',"jerd") #修改
print(alex.name) #jerd
4.###delattr删除属性###
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): self.name=name alex=A("alex") print(alex.name) #alex delattr(alex,'name') print(alex.name) #AttributeError: 'A' object has no attribute 'name'
5.##'__main__'和__name__##
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def sww(): print("爽歪歪") count=0 ###在my__moudle文件中写入 # money=100 # count=1 # import d27w6 # def sww(): # print("爽歪歪") import sys print(sys.modules['__main__']) #<module '__main__' from 'D:/lianxi/python/数据类型和函数/d27w6.py'> 如果在另一个文件中导入了当前文件,执行另一个文件会显示另一个文件名的名字 执行my__moudle文件 <module '__main__' from 'D:/lianxi/python/数据类型和函数/my_moudle.py'> print(sys.modules[__name__]) 在另一个文件中也会显示当前文件的名字 print(getattr(sys.modules[__name__],"count")) 两个文件中均显示0 print(getattr(sys.modules['__main__'],"count")) #当前文件显示0 my__moudle文件显示1
6.反射类 可以进行实例化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys main=sys.modules[__name__] class A: count=1 def __init__(self,name,age): self.name=name self.age=age cls=getattr(main,'A') stduent=cls("alex",18) ##进行实例化 print(stduent.__dict__)
反射知识点总结
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.反射类中的名字 getattr(类名,'静态属性') getattr(类名,'类方法')() getattr(类名,'静态方法')() 2.反射对象中的名字 getattr(对象名,'对象属性') getattr(对象名,'方法名')() 3.反射模块中的名字 import 模块名 getattr(模块名,'模块中的变量') getattr(模块名,'模块中的函数')() getattr(模块名,'模块中的类名') 4.反射当前模块中的名字 import sys getattr(sys.modules[__name__],'变量') getattr(sys.modules[__name__],'函数')() getattr(sys.modules[__name__],'类名') 5.反射类 import sys main=sys.modules[__name__] class A:pass cls=getattr(main,'A')
三.类中的内置方法
1.类中的内置方法(又称魔术方法 双下方法)会自动调用 __方法名__ 如__len(obj)__
是直接和python的语法隐形相关
2.__len__方法
如果类中不写def __len__(self)这个方法,会报错,在类中光兵没有len这个方法
#写的话,就自动调用了__len__这个方法,就像在实例化时会自动调用__init__方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex): self.name = name self.sex = sex def __len__(self): return len(self.__dict__) hei = A('小黑','无') print(len(hei)) #2
3.__eq__方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex): self.name = name self.sex = sex hei = A('小黑','无') hei2= A('小黑','无') print(hei.__dict__) #{'name': '小黑', 'sex': '无'} print(hei2.__dict__) #{'name': '小黑', 'sex': '无'} print(hei == hei2) #False 在类中 == 实际上是默认比较内存地址的 ###修改默认## class A: def __init__(self,name,sex): self.name = name self.sex = sex def __eq__(self, other): if self.__dict__ == other.__dict__: return True hei = A('小黑','无') hei2= A('小黑','无') print(hei == hei2) #True 自动调用__eq__
4.__format__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
format_dict={ 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 } class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __format__(self,format_spec): return format_spec.format(obj=self) s1=School('oldboy1','北京','私立') print(format(s1,format_dict['tna'])) print(format(s1,'tna'))
5.__str__ 返回值必须是字符串,否则抛出异常
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __str__(self): return str(self.__dict__) s1=School('oldboy1','北京','私立') print(str(s1)) #{'name': 'oldboy1', 'addr': '北京', 'type': '私立'} print('%s'%s1) #{'name': 'oldboy1', 'addr': '北京', 'type': '私立'} print(s1) 直接调用了__str__#{'name': 'oldboy1', 'addr': '北京', 'type': '私立'}
6.__repr__ 返回值必须是字符串,否则抛出异常
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __repr__(self): # repr是str的备胎 return 'repr : school的repr对象' s1=School('oldboy1','北京','私立') print(repr(s1)) #repr : school的repr对象 print('%r'%s1) 直接调用了__repr__#repr : school的repr对象
7.__repr__是__str__的备胎。在不存在__str__的情况下print(str(s1))会自动调用__repr__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type # def __str__(self): # return str(self.__dict__) def __repr__(self): # repr是str的备胎 return 'repr : school的repr对象' s1=School('oldboy1','北京','私立') print(str(s1)) #repr : school的repr对象 print(repr(s1)) #repr : school的repr对象