isinstance 和 issubclass
isinstance(obj,cls)检查是否obj是否是类的cls的对象
class Test:
def __init__(self, var):
self.var = var
def show(self):
print("哈哈!")
t = Test('test')
a = 'test'
print(isinstance(t, Test)) # True
print(isinstance(a, Test)) # False
isinstance和type区别
class Test(object): pass
class Test_son(Test): pass
t1 = Test()
t2 = Test_son()
print(isinstance(t2, Test)) # True # 承认继承关系
print(type(t2) is Test) # False # 不承认继承关系
a = 10
print(type(a) is int) # True
print(isinstance(a, int)) # True
# isinstance(obj,类)
# 承认继承关系的
# 类 = type(obj)
# 只承认实例化这个对象的那个类(不承认所有的继承关系)
issubclass(sub,super)检查sub类是否是super类的派生类
class Test:
def __init__(self, var):
self.var = var
def show(self):
print("哈哈!")
class Test1(Test):
pass
print(issubclass(Test1, Test)) # True
反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。python面向对象中的反射:通过字符串的形式操作对象相关的属性
- hasattr 检测是否含有某个属性
- gatattr 获取属性
- setattr 设置属性
- delattr 删除属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print("哈哈哈!")
obj = Foo("Tom", 14)
#检测某个属性
print(hasattr(obj, 'age')) # True
print(hasattr(obj, 'sex')) # False
print(hasattr(obj, 'show')) # True
# 获取属性
print(getattr(obj,'age')) # 14
print(getattr(obj,'show')) # >
# print(getattr(obj, 'sex')) # error AttributeError: 'Foo' object has no attribute 'sex'
# 修改属性
print(obj.__dict__) # {'name': 'Tom', 'age': 14}
print(setattr(obj, 'sex', "male"))
print(obj.__dict__) #{'name': 'Tom', 'age': 14, 'sex': 'male'}
print(setattr(obj, 'name', "Yang"))
print(obj.__dict__) # {'name': 'Yang', 'age': 14, 'sex': 'male'}
# 删除属性
print(obj.__dict__) # {'name': 'Yang', 'age': 14, 'sex': 'male'}
print(delattr(obj, "name"))
print(obj.__dict__) # {'age': 14, 'sex': 'male'}
print(delattr(obj,'func')) # Error AttributeError: func
反射的详细说明:
看下面的代码,是没有使用反射的
class Manager: # 管理员用户
def __init__(self, name):
self.name = name
def create_course(self): # 创建课程
print('in Manager create_course')
def create_student(self): # 给学生创建账号
print('in Manager create_student')
def show_courses(self): # 查看所有课程
print('in Manager show_courses')
def show_students(self): # 查看所有学生
print('in Manager show_students')
# 不用反射
tim = Manager('Tim')
operate_lst = ['创建课程', '创建学生账号', '查看所有课程', '查看所有学生']
for index, opt in enumerate(operate_lst, 1):
print(index, opt)
num = input('请输入您要做的操作 :')
if num.isdigit():
num = int(num)
if num == 1:
tim.create_course()
elif num == 2:
tim.create_student()
elif num == 3:
tim.show_courses()
elif num == 4:
tim.show_students()
使用反射之后:
tim = Manager('Tim')
operate_lst = [('创建课程', 'create_course'), ('创建学生账号', 'create_student'),
('查看所有课程', 'show_courses'), ('查看所有学生', 'show_students')]
for index, opt in enumerate(operate_lst, 1):
print(index, opt[0])
num = input('请输入您要做的操作 :')
if num.isdigit():
num = int(num)
if hasattr(tim, operate_lst[num - 1][1]):
getattr(tim, operate_lst[num - 1][1])()
如果使用反射呢?
# 对象名.属性名 / 对象名.方法名() 可以直接使用对象的方法和属性
# 当我们只有字符串数据类型的内容的时候
# getattr(对象名,'方法名')()
# getattr(对象名,'属性名')
类反射
class A(object):
Country = "China"
@classmethod
def show(cls):
print("国家:", cls.Country)
getattr(A, "show")() # 等价于A.show()
print(getattr(A, "Country")) # 等价于print(A.Country)
反射在模块中
import re
res = re.findall("\d+", "1abcdef123a123")
print(res) # ['1', '123', '123']
# 使用反射
res1 = getattr(re, 'findall')("\d+", "1abcdef123a123")
print(res1) # ['1', '123', '123']
# getattr(re,'findall') 等价于re.findall
import time
now = time.time()
print(now) # 1554102738.7555645
res = getattr(time, "time")()
print(res) # 1554102738.7555645
# getattr(time, "time") 等价于time.time
# 只要是a.b这种结构,都可以使用反射
# 用对象\类\模块反射,都只有以下场景
# 这种结构有两种场景
# a.b b是属性或者变量值
# getattr(a,'b') == a.b
# a.b() b是函数或者方法
# a.b()
# getattr(a,'b')()
# a.b(arg1,arg2)
# getattr(a,'b')(arg1,arg2)
# a.b(*args,**kwargs)
# getattr(a,'b')(*args,**kwargs)
反射在当前文件中的使用
怎么样查看本文件下的a变量,func函数。而不是使用打印的方式。
def func():
print("func")
a = 999
解决这个问题,需要导入内置的模块,sys,在sys中的modules方法,就所以的模块列举出来。
from sys import modules
print(modules)
上图片中标注出来的就当前的文件,则就可通过字典进行访问,而key就是"__main__",在访问当前的文件,也可以直接使用__name__。
print(__name__) # __main__ 打印__name___ 直接是__main__
from sys import modules
a = 999
def func():
print("func")
print(modules['__main__'].a) # 999
modules["__main__"].func() # func
print(modules[__name__].a) # 999
modules[__name__].func() # func
from sys import modules
a = 999
def func():
print("func")
class Test(object):
Country = "China"
@classmethod
def show(cls):
print("国家:", cls.Country)
# print(modules['__main__'].a) # 999
# modules["__main__"].func() # func
#
# print(modules[__name__].a) # 999
# modules[__name__].func() # func
if hasattr(modules[__name__], 'a'):
print(getattr(modules[__name__], 'a')) # 999
if hasattr(modules[__name__], 'func'):
getattr(modules[__name__], 'func')()
if hasattr(modules[__name__], 'Test'):
print(Test) #
print(getattr(modules[__name__], 'Test')) #
print(getattr(modules[__name__], 'Test').Country) # China
getattr(modules[__name__], 'Test').show() # 国家: China
setattr
能够通过字符串数据类型的变量名 给一个对象创建一个新的属性
class A(object):
def func(self):
print("func")
a = A()
print(a.__dict__) # {}
a.name = "Tom"
setattr(a, "name1", "Jack") # 相当于a.name1 = "Jack"
print(a.__dict__) # {'name': 'Tom', 'name1': 'Jack'}
deltattr
print(a.__dict__) # {'name': 'Tom', 'name1': 'Jack'}
delattr(a, 'name1')
print(a.__dict__) # {'name': 'Tom'}
del a.name
print(a.__dict__) # {}
总结:
# hasattr和getattr
# 只要是a.b这种结构,都可以使用反射
# 用对象\类\模块反射,都只有以下场景
# 这种结构有两种场景
# a.b b是属性或者变量值
# getattr(a,'b') == a.b
# a.b() b是函数或者方法
# a.b()
# getattr(a,'b')()
# a.b(arg1,arg2)
# getattr(a,'b')(arg1,arg2)
# a.b(*args,**kwargs)
# getattr(a,'b')(*args,**kwargs)
# 如果是本文件中的内容,不符合a.b这种结构
# 直接调用func()
# getattr(sys.modules[__name__],'func')()
# 直接使用类名 Person()
# getattr(sys.modules[__name__],'Person')()
# 直接使用变量名 print(a)
# getattr(sys.modules[__name__],'a')
# 所有的getattr都应该和hasattr一起使用
# if hasattr():
getattr()
# setattr 只用来修改或者添加属性\变量,不能用来处理函数或者是其他方法
# a.b = value
# setattr(a,'b',value)
# delattr 只用来删除 属性\变量
# del a.b 删除属性 相当于删除了a对象当中的b属性
# delattr(a,'b')