day7-python类反射

一、概述

一般的高阶语言都有反射的功能特性,python也不例外,网上资料显示,python支持类反射和模块反射,今天就先学习一下类反射的相关知识,模块反射后续再展开把。Python的类反射用于把字符串(对应于属性或方法)反射成内存中的地址对象,以便按需调用,实现某些特性的动态装配,它主要通过hasattr()、getattr()、setattr()、和delattr()来实现,类似于数据库的增删改查操作把。

二、反射函数

以下内容主要思想转自师兄张其高的博客https://www.cnblogs.com/zhangqigao/articles/6947023.html

2.1 hasattr(obj, name_str)

作用:判断一个对象obj中是否有对应的name_str字符串所代表的属性或者方法,返回布尔值。注意这里的对象可以是类,也可以是实例化的对象。

  1 class Dog(object):
  2 
  3     def __init__(self, name):
  4         self.name = name
  5 
  6     def eat(self, food):
  7         print('%s is eating %s' % (self.name, food))
  8 
  9 obj1 = Dog('XiaoHuang')
 10 
 11 print('obj1:\t %s '  % hasattr(obj1, 'name'))  #判断属性
 12 print('class Dog:\t %s' % hasattr(Dog, 'eat')) #判断方法
 13 
 14 input = input(">>>:").strip()   #动态输入字符串,动态判断
 15 print(hasattr(obj1, input))
 16 
 17 输出:
 18 obj1:	 True
 19 class Dog:	 True
 20 >>>:food
 21 False
View Code

2.2 getattr(obj, name_str)

作用:根据字符串name_str获取obj对象中的对应方法的内存地址或者对应属性的值

  1 class Dog(object):
  2 
  3     def __init__(self, name):
  4         self.name = name
  5 
  6     def eat(self, food):
  7         print('%s is eating %s' % (self.name, food))
  8 
  9 obj1 = Dog('XiaoHuang')
 10 obj2 = Dog('Bark')
 11 
 12 print('obj1:\t %s '  % getattr(obj1, 'name'))  #返回属性地址
 13 print('class Dog:\t %s' % getattr(Dog, 'eat')) #返回方法地址
 14 print('obj1:\t %s' % getattr(obj1, 'eat'))     #返回方法地址
 15 print('obj2:\t %s' % getattr(obj2, 'eat'))
 16 
 17 结果输出:
 18 obj1:	 XiaoHuang
 19 class Dog:	 <function Dog.eat at 0x00000000021CEEA0>
 20 obj1:	 <bound method Dog.eat of <__main__.Dog object at 0x00000000021CCCC0>>
 21 obj2:	 <bound method Dog.eat of <__main__.Dog object at 0x00000000021CCCF8>>
View Code

这里有一个小疑问,既然类中的方法都保存在类中,并且只保存一份,这里通过obj1和obj2去获取的类方法的地址显示是不同的,这是为什么呢?原因待脑补后补充。

2.3 setattr(obj, name_str, value)

作用:给obj对象添加一个新属性或者新方法,setattr(x, 'y', v) is equivalent to ``x.y = v''

  1. 给对象新增一个方法
      1 class Dog(object):
      2 
      3     def __init__(self, name):
      4         self.name = name
      5 
      6     def eat(self, food):
      7         print('%s is eating %s' % (self.name, food))
      8 
      9 def bulk(self):						#预期新增的方法
     10     print('%s is yelling...' % self.name)
     11 
     12 obj1 = Dog('XiaoHuang')
     13 
     14 str_input = input(">>>:").strip()
     15 setattr(obj1, str_input, bulk)
     16 func = getattr(obj1, str_input)
     17 func(obj1)
     18 
     19 print('obj1:\t %s '  % getattr(obj1, str_input))
     20 print('class Dog:\t %s' % getattr(Dog, str_input))
     21 
     22 结果输出:
     23 >>>:hehe
     24 XiaoHuang is yelling...
     25 obj1:	 <function bulk at 0x0000000001CF3E18>
     26 Traceback (most recent call last):
     27   File "D:/python/S13/Day6/testclass.py", line 28, in <module>
     28     print('class Dog:\t %s' % getattr(Dog, str_input))
     29 AttributeError: type object 'Dog' has no attribute 'hehe'
     30 
     31 Process finished with exit code 1
    View Code
    注意:
    (1) 这里新增的方法只是对实例化的对象有效,对类无效
    (2) 最后在获取func的内存地址后,也就是bulk的内存地址后,调用时需要传入实例化对象方法,因为定义的新增bulk方法有参数self,而这种动态新增的方法,参数无论是否为self,都需要手动传入

  2. 给对象新增一个属性
      1 # !/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 
      4 class Dog(object):
      5 
      6     def __init__(self, name):
      7         self.name = name
      8 
      9     def eat(self, food):
     10         print('%s is eating %s' % (self.name, food))
     11 
     12 
     13 obj1 = Dog('XiaoHuang')
     14 
     15 str_input = input(">>>:").strip()
     16 setattr(obj1, str_input, 3)
     17 print(getattr(obj1, str_input))
     18 print('obj1:\t %s '  % getattr(obj1, str_input))
     19 print('----')
     20 print(obj1.__dict__)
     21 
     22 输出:
     23 >>>:age
     24 3
     25 obj1:	 3
     26 ----
     27 {'name': 'XiaoHuang', 'age': 3}
    View Code

        上述示例程序显示,对象新增的属性可以通过__dict__来查看到,新增成功。

2.4 delattr(obj, name_str)

作用:删除obj对象中的属性或者方法,delattr(x, 'y') is equivalent to ``del x.y''

  1 class Dog(object):
  2 
  3     def __init__(self, name):
  4         self.name = name
  5 
  6     def eat(self, food):
  7         print('%s is eating %s' % (self.name, food))
  8 
  9 
 10 obj1 = Dog('XiaoHuang')
 11 
 12 str_input = input(">>>:").strip()
 13 delattr(obj1, str_input)
 14 print(Dog.__dict__)
 15 print('----')
 16 print(obj1.__dict__)
 17 print(getattr(obj1, str_input))
 18 
 19 输出:
 20 #删除属性
 21 >>>:name
 22 Traceback (most recent call last):
 23   File "D:/python/S13/Day6/testclass.py", line 24, in <module>
 24     print(getattr(obj1, str_input))
 25 AttributeError: 'Dog' object has no attribute 'name'  #访问被删除的name属性报错
 26 {'__module__': '__main__', '__init__': <function Dog.__init__ at 0x000000000219EEA0>, 'eat': <function Dog.eat at 0x000000000219EF28>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
 27 ----
 28 {} #实例的唯一属性name不见了
 29 
 30 #删除方法
 31 >>>:eat
 32 Traceback (most recent call last):
 33   File "D:/python/S13/Day6/testclass.py", line 20, in <module>
 34     delattr(obj1, str_input)
 35 AttributeError: eat   #方法删除后立马报错了
 36 
View Code

三、综合运用

上面主要讲述的属性或方法的动态增、删、改、查的基本用法,实际上删除和增加用的很少,这里结合查、删、改来简述一下综合运用。

  1 # !/usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 
  4 class Dog(object):
  5 
  6     def __init__(self, name):
  7         self.name = name
  8 
  9     def eat(self, food):
 10         print('%s is eating %s' % (self.name, food))
 11 
 12 
 13 obj1 = Dog('XiaoHuang')
 14 
 15 str_input = input(">>>:").strip()
 16 if hasattr(obj1, str_input):
 17     print('Before change')
 18     print('obj1\t%s:%s' % (str_input, getattr(obj1, str_input)))
 19     print('--------')
 20     setattr(obj1, str_input, 'Jinba')
 21     print('After change')
 22     print('obj1\t%s:%s' %(str_input, getattr(obj1, str_input)))
 23 else:
 24     setattr(obj1, str_input, None)  #对于不存在的属性设置为None,感觉意义不大?
 25     print(getattr(obj1, str_input))
 26 
 27 输出:
 28 >>>:name
 29 Before change
 30 obj1	name:XiaoHuang
 31 --------
 32 After change
 33 obj1	name:Jinba
 34 
 35 
View Code

转载于:https://www.cnblogs.com/linupython/p/9491284.html

### Python 中复杂的 Switch Case 替代方案及实现方式 #### 使用 `if...elif...else` 结构 尽管 Python 没有内置的 `switch-case` 语句,但可以通过使用 `if...elif...else` 来模拟这种行为。这种方式虽然不如某些语言中的 `switch-case` 那样简洁,但在逻辑上完全可以达到相同的效果[^3]。 ```python def get_day_name(day_num): if day_num == 0: return 'Sunday' elif day_num == 1: return 'Monday' elif day_num == 2: return 'Tuesday' elif day_num == 3: return 'Wednesday' elif day_num == 4: return 'Thursday' elif day_num == 5: return 'Friday' elif day_num == 6: return 'Saturday' else: raise ValueError('Invalid Day Number') ``` #### 利用字典映射键值对 更推荐的方法是利用字典来创建似于 `switch-case` 的结构。这种方法不仅更加灵活而且易于维护和扩展。通过定义一个函数字典,可以根据输入参数快速查找并执行相应的处理函数[^4]。 ```python def handle_sunday(): print("It's Sunday") def handle_monday(): print("It's Monday") handlers = { 0: handle_sunday, 1: handle_monday, } try: handlers[day]() # 假设变量 day 已被赋值为整数形式的工作日编号 except KeyError as e: print(f"No handler found for {e}") ``` #### 动态修改字典映射 当需求涉及到动态添加或移除选项时,基于字典的方式显得尤为强大。可以在程序运行期间随时调整映射关系,从而实现了更为复杂的应用场景下的灵活性。 ```python dynamic_handlers = {} def add_handler(key, func): dynamic_handlers[key] = func add_handler(7, lambda :print("Custom Day")) # 调用自定义处理器 dynamic_handlers.get(7, lambda :None)() ``` #### 方法分派调用 对于面向对象的设计模式下,还可以考虑采用属性作为事件触发器,并结合反射机制完成特定条件下的实例化操作或是成员方法的选择性调用。 ```python class HandlerDispatcher: @staticmethod def dispatch(event_type): method_name = f'handle_{event_type}' method = getattr(HandlerDispatcher, method_name, None) if callable(method): method() else: print(f"Unknown event type '{event_type}'.") @staticmethod def handle_login(): print("Handling login event.") @staticmethod def handle_logout(): print("Handling logout event.") # Dispatch an event based on user input or other conditions. HandlerDispatcher.dispatch('login') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值