Python之反射

一、引言

  有时候我们会碰到类似这样的需求,就是想要执行类的某个方法,或者需要对对象的某个参数赋值,而方法名或参数名已经包装在类中并不能去顶,需要通过参数传递字符串的形式输入。在这样的情况你会选择什么样的办法来解决吗?例如:

#!/usr/bin/env python
# -*- coding=utf-8 -*-

class Action(object):
    def dog(self):
        print("汪汪汪")
    def cat(self):
        print("喵喵喵")

if __name__ == "__main__":
    animal = raw_input("Please write you want the animals:")
    act = Action()
    if animal == "dog":
        act.dog()
    elif animal == "cat":
        act.cat()
执行结果如下:
"D:Program Files (x86)Python27python.exe" F:/Python/Alex/s12/Blog/reflect.py
Please write you want the animals:cat
喵喵喵

在上面的代码中使用if语句的话,就是你每写一个方法就得有一个elif语句来判断,假如有1000个方法,这样就得有1000个elif语句。这么看是不是弱爆了。那么我们就来改写上面的代码:

#!/usr/bin/env python
# -*- coding=utf-8 -*-

class Action(object):
    def dog(self):
        print("汪汪汪")
    def cat(self):
        print("喵喵喵")

if __name__ == "__main__":
    animal = raw_input("Please write you want the animals:")
    act = Action()
    if hasattr(act,animal):
        func = getattr(act,animal)
        func()
    else:
        print("You write the animal is not existed !")

执行结果如下:
"D:Program Files (x86)Python27python.exe" F:/Python/Alex/s12/Blog/reflect.py
Please write you want the animals:cat
喵喵喵

"D:Program Files (x86)Python27python.exe" F:/Python/Alex/s12/Blog/reflect.py
Please write you want the animals:snake
You write the animal is not existed !

在这里使用到了hasattr()和getattr()两个python的内建函数。通俗的对这两个内建函数讲解一下:

hasattr(act,animal) ----> 该语句的意思是:将输入的字符串与实例中的方法进行匹配,如果匹配上就返回True,匹配不上就返回False。

getattr(act,animal) ----> 该语句的意思是:将输入的字符串与实例中的方法进行匹配,如果匹配上就返回方法的内存地址,匹配不上就会有报错,见下图:

#!/usr/bin/env python
# -*- coding=utf-8 -*-

class Action(object):
    def dog(self):
        print("汪汪汪")
    def cat(self):
        print("喵喵喵")

if __name__ == "__main__":
    animal = raw_input("Please write you want the animals:")
    act = Action()
    # if hasattr(act,animal):
    func = getattr(act,animal)
    # func()
    # else:
    #     print("You write the animal is not existed !")

执行结果如下:
"D:Program Files (x86)Python27python.exe" F:/Python/Alex/s12/Blog/reflect.py
Please write you want the animals:tiger
Traceback (most recent call last):
  File "F:/Python/Alex/s12/Blog/reflect.py", line 14, in <module>
    func = getattr(act,animal)
AttributeError: 'Action' object has no attribute 'tiger'

因此在使用getattr()是可以结合hasattr()或者在方法名确定情况下进行调用!
除了getatta()和hasattr()外,还有setattr()和delattr()。

下面通过例子来全面了解这四个内建函数:

>>> class myClass(object):
...     def __init__(self):
...         self.foo = 100
... myInst = myClass()
>>> hasattr(myInst,'foo')
True
>>> getattr(myInst,'foo')
100
>>> hasattr(myInst,'bar')
False
>>> getattr(myInst,'bar')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'myClass' object has no attribute 'bar'
>>> setattr(myInst,'bar','my attr')
>>> dir(myInst)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo']
>>> getattr(myInst,'bar')
'my attr'
>>> delattr(myInst,'foo')
>>> dir(myInst)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar']
>>> hasattr(myInst,'foo')
False

二、总结:
hasattr()函数是布朗型的,它的目的就是为了决定一个对象是否有一个特定的属性,一般用于访问某属性前先做一下检查。getattr()和setattr()函数相应地取得和赋值给对象的属性,getattr()会在你试图读取一个不存在的属性时,引发AttributeError异常,除非给出那个可选的默认参数。setattr()将要么加入一个新的属性,要么取代一个已存在的属性。而delattr()函数会从一个对象中删除属性。

三、全面解析:

#!/usr/bin/env python
# -*- coding=utf-8 -*-

class Action(object):
    def __init__(self,country,zoo):
        self.country = country
        self.zoo = zoo
    def dog(self):
        print("汪汪汪")
    def cat(self):
        print("喵喵喵")

def animal_place(ins,name):
    print("the animal's place is ",name,ins.country)


if __name__ == "__main__":
    animal = raw_input("Please write you want the animals:")
    act = Action('USA','zoo')
    if hasattr(act,animal):
        func = getattr(act,animal)   #获取act.dog内存地址
        func()   #act.dong()
    else:
        print("You write the animal is not existed !")
        #想要让函数animal_place能跟实例act中方法一样执行
    setattr(act,'run',animal_place)
    act.run(act,'cat')
        #删除类Action中cat方法
    act.cat()
    delattr(Action,'cat')
    act.cat()
    #删除实例act中country的属性
    print(act.country)
    delattr(act,'country')
    print(act.country)

执行结果如下:
"D:Program Files (x86)Python27python.exe" F:/Python/Alex/s12/Blog/reflect.py
Please write you want the animals:dog
汪汪汪
("the animal's place is ", 'cat', 'USA')
喵喵喵
Traceback (most recent call last):
  File "F:/Python/Alex/s12/Blog/reflect.py", line 31, in <module>
    act.cat()
AttributeError: 'Action' object has no attribute 'cat'


USA
Traceback (most recent call last):
  File "F:/Python/Alex/s12/Blog/reflect.py", line 35, in <module>
    print(act.country)
AttributeError: 'Action' object has no attribute 'country'
原文地址:https://www.cnblogs.com/Richardzhu/p/5297119.html