当前位置:   article > 正文

python之getattr()函数和importlib库的使用

getattr


之所以使用到getattr()函数,因为我有一个需求,希望通过字符串指定使用某一个函数或者类。

1、getattr()介绍

先把官方文档的介绍抄过来:

getattr(object, name[, default])
返回对象命名属性的值。name 必须是字符串。如果该字符串是对象的属性之一,则返回该属性的值。例如, getattr(x, ‘foobar’) 等同于 x.foobar。如果指定的属性不存在,且提供了 default 值,则返回它,否则触发 AttributeError

也就是如果对象obj有一个属性为func,则可以通过以下方式获取到该属性:

# 假设func是一个函数
attr=getattr(obj,"func","not found")
attr() # 执行该函数
  • 1
  • 2
  • 3

等同于obj.func(),如果obj不存在,则attr=“not found”

2、如果对象obj是类对象

如果obj是类,我们可以通过该函数获取类的属性或者方法

通过下面的代码,我们可以获取到类的属性和方法:

# 定义一个类
class A:
    pv=3
    def __init__(self):
        pass
    def pf(self):
        print("pf")
    
    def tf(self):
        print("tf")
CA=A()	# 实例化

# 获取到CA类的pf函数
res=getattr(CA,'pf')
res()	# 执行函数
> output: pf

# 获取到CA类的变量属性pv
res=getattr(CA,"pv")
print(res) # 打印变量
> output:3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3、如果对象obj是模块对象

实际上可能更有用的是模块对象,我在一个模块中定义了很多个不同功能的类,通过字符串去获取不同的类。
先看看我们自定义一个模块结构:

utils
--__init__.py
--A.py
--B.py
--C.py
--D.py
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

__init__.py文件内容如下:

# 将这四个类暴露出去
from A import Add
from B import Sub
from C import Div
from D import Mul
  • 1
  • 2
  • 3
  • 4
  • 5

也即是在utils这个模块中,有四个类,这四个类就是utils的属性,可以通过字符串来获取某个类
现在来根据字符串获取类对象:

# 获取到加类
import utlis
clas=getattr(utlis,'Add')	# 获取到Add这个类
op=clas()	# 实例化Add这个类
  • 1
  • 2
  • 3
  • 4

其他三个类同理

4、如果查看对象obj的属性?

使用dir()函数,如果你想知道类A有哪些属性,直接dir(A);如果你想知道模块对象有哪些属性,直接dir(utils);

官方文档有详细介绍以及例子:dir([object])

你可以看到通过dir()函数列举出来的属性,也是字符串,而getattr()中也需要传入属性的字符串形式

5、总结

无论是类对象还是模块对象,或者是其他什么对象,都可以通过dir([obj])查看他们的属性,然后通过getattr(object, name[, default])来获取object中名为name的属性,如果没有名为name的属性,则返回的是default,如果没有定义default则触发AttributeError异常。

6、importlib的使用

importlib最常用的就是它的import_module方法,比如importlib.import_module("cv2")效果和import cv2是一样的,但是import_module是可以用对象的字符串名字导入的,也就是我们可以在外部直接传入字符串直接指定需要导入哪个对象。比如现在我有两个网络模型:resnet.py中有Net()类和vgg.py中有Net()类,我需要通过字符串指定用哪个类,如果用import则这样写:

if arch_name=="resnet":
	from resnet import Net
elif arch_namr=="vgg":
	from vgg import Net
net=Net()
  • 1
  • 2
  • 3
  • 4
  • 5

但是用import_module则这样写:

net=importlib.import_module("Net",package="{}".format(arch_name))
#其中相当于package.net,package可以是多级路径
  • 1
  • 2

可以看出当选择越多,import_module优势越大。
对于某些情况,对象引用路径比较复杂,可以看看这篇文章python importlib 用法小结

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/985105
推荐阅读
相关标签
  

闽ICP备14008679号