Python中利用getattr动态获取函数引用的技巧
本文介绍Python内置函数getattr的用法,演示如何获取列表、字典及模块中函数的引用。通过构建动态输出分发器的实例,展示如何根据参数名动态加载并调用对应处理函数,实现代码的灵活扩展与解耦。
getattr函数
(1)利用 getattr 函数,可以获取在运行时才能确定名称的函数的引用。
>>> li = ["Larry", "Curly"]
>>> li.pop
<built-in method pop of list object at 0x7fb75c255518>
// 该语句获取列表的 pop 方法的引用,注意该语句并不是调用 pop 方法,调用 pop 方法的应该是 li.pop(), 这里指的是方法对象本身。
>>> getattr(li, "pop")
<built-in method pop of list object at 0x7fb75c2556c8>
// 该语句也是返回 pop 方法的引用,但是此时,方法名称是作为一个字符串参数传递给 getattr 函数的, getattr 是一个有用到令人无法致信的内置函数,可以返回任何对象的任何属性。在这个例子中,对象是一个 list, 属性是 pop 方法。
>>> getattr(li, "append")("Moe")
>>> li
['Larry', 'Curly', 'Moe']
// 如果不确信它是多么的有用,试试这个: getattr 的返回值是 方法, 然后你就可以调用它,就像直接使用 li.append("Moe") 一样, 但是实际上你没有直接调用函数, 只是以字符串形式指定了函数名称。
>>> getattr({}, "clear")
<built-in method clear of dict object at 0x7fb75c273b40>
// getattr 也可以作用于字典。
>>> getattr((), "pop")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'pop'
// 理论上, getattr 可以作用于元组,但是由于元组没有方法,所以不管你指定什么属性名称 getattr 都会引发一个异常。
(2)在模块中使用 getattr:getattr 不仅适用于内置数据类型,同样适用于模块对象。
// odbchelper.py
def buildConnectionString(params):
"""Build a connection string from a dictionary of parameters.
Returns string."""
return ";".join(["%s=%s" % (k, v) for k, v in params.items()])
if __name__ == "__main__":
myParams = {"server":"mpilgrim",\
"database":"master",\
"uid":"sa",\
"pwd":"secret"
}
print buildConnectionString(myParams)
// end
>>> import odbchelper
>>> odbchelper.buildConnectionString
<function buildConnectionString at 0x7fb75c26e848>
// 该语句返回 odbchelper 模块中 buildConnectionString 函数的引用
>>> getattr(odbchelper, "buildConnectionString")
<function buildConnectionString at 0x7fb75c26e848>
// 使用 getattr, 你能够获得同一函数的同一引用, 通常, getattr(object," attribute ")等价于 object.attribute, 如果 object 是一个模块的话,那么 attribute 可能是定义在模块中的任何东西:函数、类或者全局变量。
>>> object = odbchelper
>>> method = "buildConnectionString"
>>> getattr(object, method)
<function buildConnectionString at 0x7fb75c26e848>
// object 作为一个参数传递给函数, method 是方法或者函数的名称字符串。
>>> type(getattr(object, method))
<type 'function'>
>>> import types
>>> type(getattr(object, method)) == types.FunctionType
True
// method 是函数的名称,通过获取 type 可以进行验证。
>>> callable(getattr(object, method))
True
// 由于 method 是一个函数, 所以它是可调用的。
(3)将 getattr 用作分发器
getattr 的典型应用场景之一是作为分发器。例如,若有一个程序需要以不同格式输出数据,可以为每种格式定义独立的输出函数,并通过一个统一的分发函数来调用具体的格式输出函数。
假设有一个程序,需以 HTML、XML 和普通文本格式打印站点统计数据。输出格式由命令行参数指定或保存在配置文件中。statsout 模块定义了三个函数:output_html、output_xml 和 output_text。主程序定义了一个统一的输出函数,代码如下:
import statsout
def output(data, format="text"): (1)
output_function = getattr(statsout, "output_%s" % \
format, statsout.output_text) (2)
return output_function(data) (3)
(1) output 函数接收一个必需参数 data,以及一个可选参数 format。若未指定 format 参数,默认值为 text,并调用普通文本输出函数。
(2) 将 format 参数值与字符串 “output_” 拼接,构成目标函数名,随后从 statsout 模块中获取该函数。第三个参数为默认返回值,当第二个参数指定的属性或方法不存在时,返回此默认值。这种方式便于未来扩展以支持其他输出格式,且无需修改分发函数。只需向 statsout 中添加新函数(如 output_pdf),并在调用 output 函数时将 “pdf” 作为 format 参数传入即可。
(3) 此时,可直接调用输出函数,如同调用其他普通函数。output_function 变量指向 statsout 模块中对应函数的引用。
以上关于在Python中通过getattr获取对象引用的方法分享完毕,希望能为读者提供参考,并欢迎大家继续支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













