Python面向对象 | 反射

1. 什么是反射
  反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。

2. python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)


四个内置函数:

hasattr(obj, attr): 
  这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。

getattr(obj, attr): 
  调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为‘bar‘,则返回obj.bar。
setattr(obj, attr, val): 
  调用这个方法将给obj的名为attr的值的属性赋值为val。例如如果attr为‘bar‘,则相当于obj.bar = val
delattr(obj, name)
  该函数删除该obj的一个由string指定的属性。delattr(x, ‘foobar‘)=del x.foobar

 

对实例化对象的反射

class Foo:
    f = ‘类的静态变量‘
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def say_hi(self):
        print(‘hi,%s‘%self.name)

obj=Foo(‘Tony‘,18)

#检测是否含有某属性
print(hasattr(obj,‘name‘))                  # True
print(hasattr(obj,‘say_hi‘))                # True

#获取属性
print(getattr(obj,‘name‘))                  # Tony
print(getattr(obj,‘say_hi‘))           # <bound method Foo.say_hi of <__main__.Foo object at 0x00000219B4CF6688>>
print(getattr(obj,‘aaaaaaaa‘,‘不存在啊‘))   # 不存在啊.如果不设置就会报错

#设置属性
setattr(obj,‘John‘,True)
setattr(obj,‘show_name‘,lambda self:self.name+‘君‘)
print(obj.__dict__)     # {‘name‘: ‘Tony‘, ‘age‘: 18, ‘John‘: True, ‘show_name‘: <function <lambda> at 0x000001E56C6AC048>}
print(obj.show_name(obj))                   # Tony君

#删除属性
delattr(obj,‘age‘)
delattr(obj,‘show_name‘)
# delattr(obj,‘show_name111‘    )            #不存在,则报错
print(obj.__dict__)                         # {‘name‘: ‘Tony‘, ‘John‘: True}

反射

class Foo(object):
    staticField = "old boy"

    def __init__(self):
        self.name = ‘wupeiqi‘

    def func(self):
        return ‘func‘

    @staticmethod
    def bar():
        return ‘bar‘


print (getattr(Foo, ‘staticField‘))        # 注意第二个参数无论是静态属性、对象属性、方法,都要加单引号‘’
print (geattr(Foo, ‘func‘))
print (getattr(Foo, ‘bar‘))

当前模块的反射

import time          # 一个py文件就是一个模块
time.time()

if hasattr(time,‘time‘):
    print(time.time)
    print(getattr(time,‘time‘)())

‘‘‘
执行输出:
<built-in function time>
1569572942.545881
‘‘‘
import sys
def s1():
    print(‘s1‘)
def s2():
    print(‘s2‘)

current_module = sys.modules[__name__]
print(current_module)
print(hasattr(current_module, ‘s1‘))
print(getattr(current_module, ‘s2‘))

‘‘‘
执行输出:
<module ‘__main__‘ from ‘C:/Users/Administrator/Desktop/temp/test.py‘>
True
<function s2 at 0x0000026BFDF98048>
‘‘‘

 

其他模块的反射

"""
程序目录:
    module.py
    test.py
"""


# 模块module.py中的代码
class A:
    name = "module"

    def func():
        print(‘我是module模块的func‘)


# test.py中的代码
import module

# 方法一:
clas = getattr(module, ‘A‘)
print(clas.name)                    # module

# 方法二:
print(getattr(module.A, ‘name‘))    # module
getattr(module.A, ‘func‘)()         # 我是module模块的func

假设有一个文件名userinfo,需要重命名

# 第一种:常规办法
import os
os.rename(‘userinfo‘,‘user‘)

# 第二种:使用反射
import os
getattr(os,‘rename‘)(‘userinfo‘,‘user‘)      # getattr(os,‘rename‘) 相当于os.rename

总结:

1. 类使用类命名空间中的名字
  getattr(类名,‘名字‘)

2. 对象使用对象能用的方法和属性
  getattr(对象名,‘名字‘)

3. 从自己所在的模块中使用自己名字
  import sys

  getattr(sys.modules[‘__main__‘],名字)

4. 模块使用模块中的名字
  导入模块

  getattr(模块名,‘名字‘)

import os ;
getattr(os,‘rename‘)(‘user‘,‘user_info‘)

相关推荐