Python 反射

一、前言

def func():
    print('func 函数..')


s1 = 'func'
s1()   #TypeError: 'str' object is not callable
'func'()  #TypeError: 'str' object is not callable

我们可以通过fun()去调用一个函数,但是不能使用一个字符串'func'()去调用一个函数

二、根据用户输入,显示不同页面

def login():print('登陆..')
def index():print('主页..')
def exitout():print('退出..')
def Main():
    content = input('>>>')
    if content == 'login':
        login()
    elif content == 'index':
        index()
    elif content == 'exitout':
        exitout()

Main()

有一个Main()函数,根据用户输入显示不同的相应页面,如果我们后续很多功能需要扩展的话,需要很多elif来判断。

三、反射

class Main(object):
    def login(self):print('登陆..')
    def index(self):print('主页..')
    def exitout(self):print('退出..')


content = input('>>>')
main = Main()
getattr(main,content)()

首先说一下getattr(),getattr需要两个参数:第一个参数可以是类或者是对象,第二个参数是一个字符串。

反射的本质其实就是利用字符串的形式去对象或者类中寻找属性和方法,一种基于字符串的事件驱动。

四、反射中其他方法

如果getattr()没查到值,会报AttributeError: 'Main' object has no attribute 'df'错误,通常在getattr()前使用hasattr()判断一下:

class Main(object):
    def login(self):print('登陆..')
    def index(self):print('主页..')
    def exitout(self):print('退出..')


content = input('>>>')
main = Main()
if hasattr(main,content):  #hasattr()返回bool类型。如果有content变量返回True
    getattr(main,content)()
else:
    prin('404')

 四、反射操作类中的属性和方法

class Student(object):
    school = '北京大学'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    @staticmethod
    def login():
        user = input('用户名:>>')
        passwd = input('密码:>>')
        if user == 'laowang' and passwd == '123':
            return 'OK'
        else:
            return 'Error'
    @classmethod
    def getInfo(self):
        return '老王,密码:123.'
content = input('>>')
# print(getattr(Student,content))  #北京大学 访问类的静态属性
print(getattr(Student,content)()) #OK 访问类的静态函数

'''
结论:
    1.可以访问类的静态属性
    2.可以访问类的静态函数 @staticmethod
    3.可以访问类方法   @classmethod
'''

五、反射操作对象的属性、方法

class Student(object):
    school = '北京大学'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def getInfo(self):
        return str('姓名:%s,年龄:%s.'%(self.name,self.age))
stu = Student('老王',30)
content = input('>>')
# print(getattr(stu,content)) #name -- > 老王
# print(getattr(stu,content)) #age ---> 30
# print(getattr(stu,content)())#姓名:老王,年龄:30.
'''
结论:
    1.可以操作对象属性
    2.可以操作对象方法
'''

六、反射操作导入模块

import My_moudle

#1.操作模块的变量   getattr(模块名,'字符串')
print(getattr(My_moudle,'money'))

#2.操作模块中的函数,getattr(模块名,'字符串')()  加括号表示执行
print(getattr(My_moudle,'print_money')())

#3.操作模块中的类
print(getattr(My_moudle,'Student')) #<class 'My_moudle.Student'>
stu = getattr(My_moudle,'Student')() #进行实例化
stu.print_info()

'''
1.操作模块中的变量
2.操作模块中的函数
3.操作模块中的类,并进行了实例化
'''

七、通过反射操作当前模块

由于getattr(模块名,'字符串'),那么在当前的模块中,模块名是什么呢?

我们可以通过sys.modules来查看 --> __main__,__main__变量的值永远都是当前执行的模块,如果另一个模块引入了当前模块,那么__main__的值将会是另一个模块,会导致变量等找不到等错误。

所以模块名可以使用__name__

需要注意的是sys.modules是一个字典,sys.modules['__main__'],得到的是当前模块的内存地址,我们通过这个内存地址来操作当前模块中的变量、函数、类、对象等。

test1 = 'test.py'

def print_test1():
    print(test1)

class Student(object):
    def print_info(self):
        print('test.py 中Student类')


#1.操作当前模块的变量,通过sys.modules[__name__]来得到当前模块
# print(sys.modules[__name__]) #<module '__main__' from 'D:/PythonObject/day27/test.py'>
# print(getattr(sys.modules[__name__],'test1')) #test.py

#2.访问当前模块的函数
# getattr(sys.modules[__name__],'print_test1')() #test.py

#3.访问当前模块的类,并实例化对象,操作对象中的方法
stu = getattr(sys.modules[__name__],'Student')()
stu.print_info()  #test.py 中Student类

 

posted @ 2018-03-12 18:34  短毛兔  阅读(279)  评论(0编辑  收藏  举报