zoukankan      html  css  js  c++  java
  • 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'
  • 相关阅读:
    opencv-python与c++ opencv中的一些区别和基础的知识
    使用TensorFlow Object Detection API+Google ML Engine训练自己的手掌识别器
    使用Google Cloud Platform构建机器学习项目-宠物识别
    dlib下训练自己的物体检测器--手的检测
    python学习--Linux下dlib安装(主要是cmake和boost的安装)
    Python学习--使用dlib、opencv进行人脸检测标注
    《Python网络编程》学习笔记--UDP协议
    《Python网络编程》学习笔记--从例子中收获的计算机网络相关知识
    《Python网络编程》学习笔记--使用谷歌地理编码API获取一个JSON文档
    Spring Cloud Gateway:使用ReadBodyPredicateFactory读取request的body,可能无法匹配404
  • 原文地址:https://www.cnblogs.com/Richardzhu/p/5297119.html
Copyright © 2011-2022 走看看