4.4. 通过 getattr 获取对象引用

你已经知道 Python 函数是对象。你不知道的是,使用 getattr 函数,可以得到一个直到运行时才知道名称的函数的引用。

例 4.10. getattr 介绍

>>> li = ["Larry", "Curly"]
>>> li.pop                       
<built-in method pop of list object at 010DF884>
>>> getattr(li, "pop")           
<built-in method pop of list object at 010DF884>
>>> getattr(li, "append")("Moe") 
>>> li
["Larry", "Curly", "Moe"]
>>> getattr({}, "clear")         
<built-in method clear of dictionary object at 00F113D4>
>>> getattr((), "pop")           
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'pop'
该语句获取列表的 pop 方法的引用。注意该语句并不是调用 pop 方法;调用 pop 方法的应该是 li.pop()。这里指的是方法对象本身。
该语句也是返回 pop 方法的引用,时时彩计划软件公式:但是此时,方法名称是作为一个字符串参数传递给 getattr 函数的。getattr 是一个有用到令人无法致信的内置函数,可以返回任何对象的任何属性。在这个例子中,对象是一个 list,属性是 pop 方法。
如果不确信它是多么的有用,试试这个:getattr 的返回值 方法,然后你就可以调用它,就像直接使用 li.append("Moe") 一样。但是实际上你没有直接调用函数;只是以字符串形式指定了函数名称。
getattr 也可以作用于字典。
理论上,getattr 可以作用于元组,但是由于元组没有方法,所以不管你指定什么属性名称 getattr 都会引发一个异常。

4.4.1. 用于模块的 getattr

getattr 不仅仅适用于内置数据类型,也可作用于模块。

例 4.11. apihelper.py 中的 getattr 函数

>>> import odbchelper
>>> odbchelper.buildConnectionString             
<function buildConnectionString at 00D18DD4>
>>> getattr(odbchelper, "buildConnectionString") 
<function buildConnectionString at 00D18DD4>
>>> object = odbchelper
>>> method = "buildConnectionString"
>>> getattr(object, method)                      
<function buildConnectionString at 00D18DD4>
>>> type(getattr(object, method))                
<type 'function'>
>>> import types
>>> type(getattr(object, method)) == types.FunctionType
True
>>> callable(getattr(object, method))            
True
该语句返回 odbchelper 模块中 buildConnectionString 函数的引用,第 2 章 第一个 Python 程序 你已经研习过这个方法了。(你看到的这个十六进制地址是我机器上的;你的输出结果会有所不同。)
使用 getattr,你能够获得同一函数的同一引用。通常,getattr(object, "attribute") 等价于 object.attribute。如果 object 是一个模块的话,那么 attribute 可能是定义在模块中的任何东西:函数、类或者全局变量。
接下来的是你真正用在 info 函数中的东西。object 作为一个参数传递给函数; method 是方法或者函数的名称字符串。
在这个例子中,method 是函数的名称,通过获取 type 可以进行验证。
由于 method 是一个函数,所以它是可调用的

4.4.2. getattr 作为一个分发者

getattr 常见的使用模式是作为一个分发者。举个例子,如果你有一个程序可以以不同的格式输出数据,你可以为每种输出格式定义各自的格式输出函数,然后使用唯一的分发函数调用所需的格式输出函数。

例如,让我们假设有一个以 HTMLXML 和普通文本格式打印站点统计的程序。输出格式在命令行中指定,或者保存在配置文件中。statsout 模块定义了三个函数:output_htmloutput_xmloutput_text。然后主程序定义了唯一的输出函数,如下:

例 4.12. 使用getattr 创建分发者


import statsout

def output(data, format="text"):                              
    output_function = getattr(statsout, "output_%s" % format) 
    return output_function(data)                              
output 函数接收一个必备参数 data,和一个可选参数 format。如果没有指定 format 参数,其缺省值是 text 并完成普通文本输出函数的调用。
你可以连接 format 参数值和 "output_" 来创建一个函数名称作为参数值,然后从 statsout 模块中取得该函数。这种方式允许今后很容易地扩展程序以支持其它的输出格式,而且无需修改分发函数。所要做的仅仅是向 statsout 中添加一个函数,比如 output_pdf,之后只要将 “pdf” 作为 format 的参数值传递给 output 函数即可。
现在你可以简单地调用输出函数,就像调用其它函数一样。output_function 变量是指向 statsout 模块中相应函数的引用。

你是否发现前面示例的一个 Bug?即字符串和函数之间的松耦合,而且没有错误检查。如果用户传入一个格式参数,但是在 statsout 中没有定义相应的格式输出函数,会发生什么呢?还好,getattr 会返回 None,它会取代一个有效函数并被赋值给 output_function,然后下一行调用函数的语句将会失败并抛出一个异常。这种方式不好。

值得庆幸的是,getattr 能够使用可选的第三个参数,一个缺省返回值。

例 4.13. getattr 缺省值


import statsout

def output(data, format="text"):
    output_function = getattr(statsout, "output_%s" % format, statsout.output_text)
    return output_function(data) 
这个函数调用一定可以工作,因为你在调用 getattr 时添加了第三个参数。第三个参数是一个缺省返回值,如果第二个参数指定的属性或者方法没能找到,则将返回这个缺省返回值。

正如你所看到,getattr 是相当强大的。它是自省的核心,在后面的章节中你将看到它更强大的示例。

吉林时时彩群号大全 17500乐彩网走势图 重庆时时彩专家 北京时时彩开奖走势图 重庆时时彩组后三走势
时时彩后二稳赚技巧 江西时时彩免费计划软件 阿拉丁时时彩软件 时时彩彩票论坛 时时彩遗漏软件
重庆时时彩怎么样稳赚 内蒙古时时彩黑彩票骗局 澳门银河反水怎么算 时时彩龙虎 时时彩组6技巧
时时彩软件绑定机器码 时时彩招代理 时时彩四星软件 彩度时时彩软件 江西11选5彩经网
河北快3开奖结果 好彩1最新预测 腾讯分分彩官网 极速时时彩是哪里开的 广东十一选五360
重庆幸运农场开奖 山东十一选五遗漏 新疆35选7中奖 足球上帝 内蒙古十一选五开奖号
北京赛车pk10讨论群 新疆18选7100走势圈 韩国快乐8开奖号码 内蒙古11选5走试图 快速下跌形态图解?彩票开奖结果?吉林快3追号计划软件?福彩快三福建遗漏数据
地方彩河北20选5开奖公告 炸金花棋牌游戏 体彩排列5助赢软件 急速赛车内购破解版下载 体彩走势图