• 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:	 %s '  % hasattr(obj1, 'name'))  #判断属性
     12 print('class Dog:	 %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:	 %s '  % getattr(obj1, 'name'))  #返回属性地址
     13 print('class Dog:	 %s' % getattr(Dog, 'eat')) #返回方法地址
     14 print('obj1:	 %s' % getattr(obj1, 'eat'))     #返回方法地址
     15 print('obj2:	 %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:	 %s '  % getattr(obj1, str_input))
       20 print('class Dog:	 %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:	 %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:	 %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	%s:%s' % (str_input, getattr(obj1, str_input)))
     19     print('--------')
     20     setattr(obj1, str_input, 'Jinba')
     21     print('After change')
     22     print('obj1	%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

  • 相关阅读:
    05---二叉树---20195106023---王亚威.c
    05---二叉树---20195106043---方传祥.c
    05---二叉树---20195106006---陈辉.c
    05---二叉树---20195106064---陈昕.c
    05---二叉树---20195106100---李遂勋.c
    2020下---3D建模---作业---blender
    nothing provides python(abi) = 3.8 needed by VirtualBox-6.1-6.1.16_140961_fedora32-1.x86_64
    el-table、pl-table(u-table)、ux-grid解决表格问题的实例(大数据量)
    1800*1【Codeforces Round #665 (Div. 2) D】Maximum Distributed Tree
    【Educational Codeforces Round 97 (Rated for Div. 2) C】Chef Monocarp
  • 原文地址:https://www.cnblogs.com/linupython/p/9491284.html
Copyright © 2020-2023  润新知