您在这里:首页 > 深入 Python > 自省的强大功能 > 使用 getattr 获取对象引用 | << >> | ||||
深入 Python从 Python 新手到专业人士 |
您已经知道 Python 函数是对象。您不知道的是,您可以使用 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 方法;那将是 li.pop()。这是方法本身。 |
![]() |
这也返回对 pop 方法的引用,但这次,方法名称作为字符串参数指定给 getattr 函数。getattr 是一个非常有用的内置函数,它返回任何对象的任何属性。在这种情况下,对象是一个列表,属性是 pop 方法。 |
![]() |
如果它还没有完全渗透到它的用处,请尝试以下操作:getattr 的返回值 是 该方法,然后您可以像直接说 li.append("Moe") 一样调用它。但您没有直接调用该函数;您改为将函数名称指定为字符串。 |
![]() |
getattr 也适用于字典。 |
![]() |
理论上,getattr 适用于元组,但 元组没有方法,因此无论您给出什么属性名称,getattr 都会引发异常。 |
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
![]() |
这将返回对 第 2 章,您的第一个 Python 程序 中研究的 odbchelper 模块中的 buildConnectionString 函数的引用。(您看到的十六进制地址特定于我的机器;您的输出将有所不同。) |
![]() |
使用 getattr,您可以获得对同一函数的相同引用。通常,getattr(对象, "属性") 等效于 对象.属性。如果 对象 是模块,则 属性 可以是模块中定义的任何内容:函数、类或全局变量。 |
![]() |
这就是您在 info 函数中实际使用的内容。对象 作为参数传递给函数;方法 是一个字符串,它是方法或函数的名称。 |
![]() |
在这种情况下,方法 是函数的名称,您可以通过获取其 type 来证明这一点。 |
![]() |
由于 方法 是一个函数,因此它是 可调用的。 |
getattr 的常见用法模式是作为调度器。例如,如果您有一个程序可以以各种不同的格式输出数据,则可以为每种输出格式定义单独的函数,并使用单个调度函数来调用正确的函数。
例如,假设有一个程序以 HTML、XML 和纯文本格式打印站点统计信息。输出格式的选择可以在命令行上指定,也可以存储在配置文件中。一个 statsout 模块定义了三个函数,output_html、output_xml 和 output_text。然后主程序定义了一个输出函数,如下所示
import statsout def output(data, format="text"):output_function = getattr(statsout, "output_%s" % format)
return output_function(data)
![]()
您看到上一个示例中的错误了吗?这是字符串和函数的非常松散的耦合,并且没有错误检查。如果用户传入的格式在 statsout 中没有定义相应的函数,会发生什么情况?好吧,getattr 将返回 None,它将被分配给 output_function 而不是有效的函数,并且尝试调用该函数的下一行将崩溃并引发异常。那太糟糕了。
幸运的是,getattr 接受一个可选的第三个参数,即默认值。
import statsout def output(data, format="text"): output_function = getattr(statsout, "output_%s" % format, statsout.output_text) return output_function(data)![]()
如您所见,getattr 非常强大。它是自省的核心,您将在后面的章节中看到更强大的例子。
<< 使用 type、str、dir 和其他内置函数 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
过滤列表 >> |