python面向对象编程-反射/自省
对于面向对象编程,我们通常对对象中的成员操作如下:
class foo:
def __init__(self,n,a):
self.name = n
self.age = a
def show(self):
return '%s,%s'%(self.name,self.age)
obj = foo('gao',18)
print(obj.name) # gao
print(obj.age) # 18
print(obj.show()) # gao,18
上述方式name
为一个变量,当我们只有一个字符串时,我们又如何拿出对应的内容呢?
class foo:
def __init__(self,n,a):
self.name = n
self.age = a
def show(self):
return '%s,%s'%(self.name,self.age)
obj = foo('gao',18)
a = 'name'
# 1 纯属投机取巧,没有任何技术上的含义
if a == 'name':
print(obj.name) # gao
# 2 利用__dict__方法返回的字典去索引指定字符串
print(obj.__dict__[a]) # gao
第三种方法就是马上要学的:反射
反射:通过字符串的形式操作对象中的成员!!!
反射提供的方法:
getattr
获取对象成员
hasattr
判断对象是否存在成员
setattr
设置一个对象成员
delattr
删除一个对象成员
class foo:
def __init__(self,n,a):
self.name = n
self.age = a
def show(self):
return '%s,%s'%(self.name,self.age)
obj = foo('gao',18)
# hasattr 判断是否存在 返回布尔值
print(hasattr(obj,'name')) # True
print(hasattr(obj,'name1')) # False
print(hasattr(obj,'show')) # True
# getattr 获取指定成员 当指定的成员不存在时,会直接报错
print(getattr(obj,'name')) # gao
print(getattr(obj,'show')) # <bound method foo.show of <__main__.foo object at 0x000001DACA66E198>>
print(getattr(obj,'show')()) # gao,18
# 当设值第三个参数时(默认值),获取不存在的属性时,不会报错,会直接返回设置的默认值
print(getattr(obj,'attr','无此参数')) # ‘无此参数’
# setattr 设置对象成员
setattr(obj,'sex','men')
print(obj.sex) # men
# delattr 删除对象成员
print(obj.name) # gao
delattr(obj,'name')
print(obj.name) # AttributeError: 'foo' object has no attribute 'name'
有句话叫,在python中,一切皆对象,故反射的方式,是不是不仅仅只用在类中:
创建一个名为s1.py
的模块,写入下代码:
#!-*- coding:utf-8 -*-
#date: 2020/4/21
name = 'gao'
def foo():
return 'hello world'
创建一个名为s2.py
的模块,写入以下代码:
#!-*- coding:utf-8 -*-
#date: 2020/4/21
import s1
# 正常逻辑操作
print(s1.name) # gao
print(s1.foo()) # hello world
# 使用反射操作
# 对于变量操作
print(getattr(s1,'name')) # gao
# 对于函数操作
a = getattr(s1,'foo')
print(a) # getattr(s1,'foo')
print(a()) # hello world
# 对于类操作
x = getattr(s1,'foo1')
print(x) # <class 's1.foo1'>
obj = x()
print(obj) # <s1.foo1 object at 0x000001498464A4E0>
print(obj.name) # gao
此做法是一个最常用的:
在一个最常用的页面,存在n个按钮,每个按钮,对应调用不同的函数;
当我们监控调用时,如果不这么使用,我们需要花很长的代码去给其做对应,但使用反射时,只需要做两点即可:
1、判断索引的对象是否存在;
2、存在即调用即可;