python3 反射

hasattr(obj, str) 判断obj对象中是否有str成员

getattr(obj, str) 从obj对象中获取str成员

setattr(obj, str, value) 把obj对象中的str设置为value

delattr(obj, str) 从obj对象中删除str成员

以上方法都是在内存中执行的,不会影响源代码

先看下hasattr和getattr的使用

# master.py
name = "lily"


def func1():
    print("我是func1")


def func2():
    print("我是func2")


def func3():
    print("我是func3")


class Person:
    pass
# test反射.py
from types import FunctionType
import master


while 1:
    inp = input("请输入你要执行的方法:").strip()
    if hasattr(master, inp):
        fn = getattr(master, inp)
        if callable(fn):  # 同 if isinstance(fn, FunctionType):
            fn()
        else:
            print(fn)
    else:
        print("输入的变量名不存在")

执行test反射.py的结果:

请输入你要执行的方法:name
lily
请输入你要执行的方法:func1
我是func1
请输入你要执行的方法:func2
我是func2
请输入你要执行的方法:aa
输入的变量名不存在
请输入你要执行的方法:Person
<class 'master.Person'>
请输入你要执行的方法:

接下来看下setattr的使用(只是在内存中修改,对源代码无影响)

# setattr实例.py
import master

fn = lambda: print("我是修改后的func1")  # 无参数无返回值的函数
# def fn():  # 同fn = lambda: print("我是修改后的func1")
#     print("我是修改后的func1")
master.func1()
setattr(master, "func1", fn)
master.func1()

执行setattr实例.py的结果:

我是func1
我是修改后的func1

 delattr的使用(只是在内存中删除,对源代码无影响)

import master


print(master.func1)
delattr(master, "func1")
print(master.func1)  # AttributeError: module 'master' has no attribute 'func1'

执行结果:

Traceback (most recent call last):
  File "G:/python28/code/python-28/day07/反射/delattr的操作.py", line 6, in <module>
    print(master.func1)
AttributeError: module 'master' has no attribute 'func1'
<function func1 at 0x00000000029779D8>

一定要注意反射在类中的使用,不能建议使用getattr(类名, 方法名)

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def func(self):
        print(f"我是func 我的名字是{self.name}")


p = Person("lily", 18)
f1 = getattr(p, "func")
f1()
f2 = getattr(Person, "func")  
# f2()  # 报错TypeError: func() missing 1 required positional argument: 'self'
f2(p)

执行结果:

我是func 我的名字是lily
我是func 我的名字是lily

总结:

  fn = getattr(obj, str1) 相当于fn = obj.str1

  fn() 相当于obj.str1()

  f1 = getattr(p, "func") 相当于f1 = p.func

  f1() 相当于p.func() 因为 func是实例方法,所以对象调用实例方法是正常的。如果这里看着费劲或者看不懂,请先 https://www.cnblogs.com/lilyxiaoyy/p/11988523.html

  f2 = getattr(Person, "func") 相当于 f2 = Person.func

  f2() 相当于Pereson.func() 这里肯定是报错的,因为实例方法的一个参数默认是对象self

  f2(p) 相当于Person.func(p) 手动把对象p传递给实例方法的第一个参数,不推荐使用类名调用实例方法。

反射在类中的使用

# 反射在类中的使用.py
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def func(self):
        print(f"我是func 我的名字是{self.name}")


p = Person("lily", 18)

if hasattr(p, "func"):  # attribute 判断p对象中是否有func属性
    fn = getattr(p, "func")  # 从p对象中获取func属性
    if callable(fn):  # 判断是否可以被调用  + ()
        fn()

# delattr(p, "name")  # 删除p对象中的name属性
# print(p.name)

p2 = Person("lucy", 16)
print(p2.name)

setattr(p, "address", "北京市八大胡同")  # 给p对象设置address属性,值为北京市八大胡同
print(p.address)  # 北京市八大胡同

setattr(p, "func2", lambda: print("我是func2"))
p.func2()

 执行结果:

我是func 我的名字是lily
lucy
北京市八大胡同
我是func2
原文地址:https://www.cnblogs.com/lilyxiaoyy/p/10917151.html