zoukankan      html  css  js  c++  java
  • Python基础-21反射

    21 反射

    21.1 反射概念

        反射主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。在Python中最重要的4个方法如下所示:

    • getattr:获取指定字符串名称的对象属性
    • setattr:给对象添加类属性
    • hasattr:判断对象是否存在某个对应的对象
    • delattr:删除指定的属性

        我们先来定义一个类,如下所示:

    class Fruit:
    
        def __init__(self,name,color):
            self.name=name
            self.color=color
    
        def __str__(self):
            return f"Fruit is {self.name} color is {self.color}"
    
        def buy(self,price,totalWeight):
            return f"Fruit is {self.name},total price is {price*totalWeight}"
    

    21.2 反射常用方法

    21.2.1 getattr

        getattr主要用来获取指定字符串名称的对象属性,其使用方法如下所示:

    getattr(object, name:string[, default]) -> value
    
    • name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参
    • 如果属性存在,则返回其属性值,不存在则分为两种情况,一种是没有default参数时,则直接报错,如给定了default参数,对象没有其属性,则返回给定的default值
    • 如果获取的是类方法,则返回函数对象

        以前面定义的Fruit类为例

    # 实例化一个类
    apple=Fruit("apple","red")
    # 利用反射获取类属性
    print(getattr(apple,"name"))
    print(getattr(apple,"color"))
    # 利用反射获取类方法
    print(getattr(apple,"buy"))
    # 利用反射获取不存在的属性且有默认值
    print(getattr(apple,"test","123"))
    # 利用反射获取不存在的属性且没有默认值 - 报错
    print(getattr(apple,"test"))
    

    输出结果如下所示:

    apple
    red
    <bound method Fruit.buy of <__main__.Fruit object at 0x000001E70B356288>>
    123
    Traceback (most recent call last):
      File "C:/Users/Surpass/Documents/PycharmProjects/SADCI/TempCode/reflectorSample.py", line 24, in <module>
        print(getattr(apple,"test"))
    AttributeError: 'Fruit' object has no attribute 'test'
    

    21.2.2 setattr

        setattr主要用于给对象添加一个类属性,如果添加的属性已经存在,则对其进行更新,否则则进行创建,其使用方法如下所示:

    setattr(object, name:string, value)
    

    name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参

        示例如下所示:

    # 实例化一个类
    apple=Fruit("apple","red")
    # 为实例添加一个类属性,并设置其值
    setattr(apple,"destination","china")
    print(f'第一次添加类属性,其值为(添加操作):{getattr(apple,"destination")}')
    setattr(apple,"destination","USA")
    print(f'第二次添加类属性,其值为(更新操作):{getattr(apple,"destination")}')
    

    输出结果如下所示:

    第一次添加类属性,其值为(添加操作):china
    第二次添加类属性,其值为(更新操作):USA
    

    21.2.3 hasattr

        hasattr常用于判断对象中是否存在其属性或方法,常用用法如下所示:

    hasattr(object, name:string) -> bool
    

    name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参

        示例如下所示:

    # 实例化一个类
    apple=Fruit("apple","red")
    # 判断属性或方法是否存在
    print(f'对象是否存在其属性 name - {True if hasattr(apple,"name") else False }')
    print(f'对象是否存在其属性 country - {True if hasattr(apple,"country") else False }')
    print(f'对象是否存在其方法 buy - {True if hasattr(apple,"buy") else False }')
    

    输出结果如下所示:

    对象是否存在其属性 name - True
    对象是否存在其属性 country - False
    对象是否存在其方法 buy - True
    

    21.2.4 delattr

        delattr常用于删除指定的属性,但不能用于方法,常用用法如下所示:

    delattr(object, name:string)
    

    name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参

        示例如下所示:

    # 实例化一个类
    apple=Fruit("apple","red")
    delattr(apple,"name")
    # 判断属性或方法是否存在
    print(f'对象是否存在其属性 name - {True if hasattr(apple,"name") else False }')
    print(f'对象是否存在其属性 country - {True if hasattr(apple,"country") else False }')
    print(f'对象是否存在其方法 buy - {True if hasattr(apple,"buy") else False }')
    

    输出结果如下所示:

    对象是否存在其属性 name - False
    对象是否存在其属性 country - False
    对象是否存在其方法 buy - True
    

    在日常使用,一般会进行判断属性是否存在,然后再调用获取、添加和删除方法

    21.3 示例

        以下用一个简单的示例来解释,反射在实际的应用案例。现在有一个场景,就是根据传入的不同的模块名称,调用不同的模块所对应方法,代码如下所示:

    class ReflectSample:
    
        def moduleA(self):
            print("我是moduleA")
    
        def moduleB(self):
            print("我是moduleB")
    
        def moduleC(self):
            print("我是moduleC")
    
        def moduleD(self):
            print("我是moduleD")
    
    • 方法一:
    while True:
        reflectSample=ReflectSample()
        choice=input("请输入模块名称")
        if choice == "moduleA":
           reflectSample.moduleA()
        elif choice == "moduleB":
            reflectSample.moduleB()
        elif choice == "moduleC":
            reflectSample.moduleC()
        elif choice == "moduleD":
            reflectSample.moduleD()
        else:
            print("输入的模块不存在")
    

    测试结果如下所示:

    请输入模块名称moduleA
    我是moduleA
    请输入模块名称moduleD
    我是moduleD
    请输入模块名称moduleF
    输入的模块不存在
    
    • 方法二:
    while True:
        reflectSample = ReflectSample()
        choice = input("请输入模块名称")
        if hasattr(reflectSample,choice):
            func=getattr(reflectSample,choice)
            func()
        else:
            print("输入的模块不存在")
    

    测试结果如下所示:

    请输入模块名称moduleA
    我是moduleA
    请输入模块名称moduleD
    我是moduleD
    请输入模块名称moduleF
    输入的模块不存在
    

    两种方法一对比,自然就觉得方法二更简洁,也更容易维护,更不用担心类中有很多个方法。

    本文地址:https://www.cnblogs.com/surpassme/p/12902742.html

    本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注:
    MyQRCode.jpg

  • 相关阅读:
    【bzoj2882】工艺 后缀自动机+STL-map
    【bzoj3884】上帝与集合的正确用法 扩展欧拉定理
    【bzoj1475】方格取数 网络流最小割
    【bzoj4825】[Hnoi2017]单旋 线段树+STL-set
    【bzoj4448】[Scoi2015]情报传递 主席树
    【bzoj1803】Spoj1487 Query on a tree III DFS序+主席树
    【bzoj2127】happiness 网络流最小割
    【bzoj2431】[HAOI2009]逆序对数列 dp
    【bzoj4245】[ONTAK2015]OR-XOR 贪心
    【bzoj4066】简单题 KD-tree
  • 原文地址:https://www.cnblogs.com/surpassme/p/12902742.html
Copyright © 2011-2022 走看看