一.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
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()
View Code
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删除属性###
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'
View Code
5.##'__main__'和__name__##
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
View Code
6.反射类 可以进行实例化
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__)
View Code
反射知识点总结
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')
View Code
三.类中的内置方法
1.类中的内置方法(又称魔术方法 双下方法)会自动调用 __方法名__ 如__len(obj)__
是直接和python的语法隐形相关
2.__len__方法
如果类中不写def __len__(self)这个方法,会报错,在类中光兵没有len这个方法
#写的话,就自动调用了__len__这个方法,就像在实例化时会自动调用__init__方法
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
View Code
3.__eq__方法
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__
View Code
4.__format__
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'))
View Code
5.__str__ 返回值必须是字符串,否则抛出异常
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': '私立'}
View Code
6.__repr__ 返回值必须是字符串,否则抛出异常
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对象
View Code
7.__repr__是__str__的备胎。在不存在__str__的情况下print(str(s1))会自动调用__repr__
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对象
View Code