在getattr()中有两个参数是什么意思?
在Python的官方文档中,我看到了getattr()的常见用法:
getattr(object, name[, default])
我对这个用法理解得还不错。比如,我可以这样做:
>>> def a():
... pass
...
>>> c = 2
>>> getattr(a, 'b', c)
2
但是在我现在查看的代码中,作者使用了一种模式:
getattr(a, b.x)(b.y)
而且我甚至在'a'这个对象中找不到'b'!
这让我很困惑,这段代码是什么意思呢?
附录1:
getattr()出现在很多导入语句之间。 而原始的表达式是这样的:
from tornado.options import define, options
import settings
getattr(settings, options.env)(options.server_name)
4 个回答
他必须做一些像这个例子一样的事情:
>>> a = 10
>>> class B:
... def __init__(self, y):
... self.y = y
... def x(self, y):
... return y
...
>>> b = B(20)
>>> getattr(a, 'b', b.x)(b.y)
20
>>>
这里,b
是一个对象,它有一个叫 x
的“函数属性”,这个属性可以接受 y
作为 b
的另一个属性。
getattr(a, 'b', b.x)
返回的是一个函数引用,在我的例子中,它返回的是 x
,所以在我的例子中,getattr(a, 'b', b.x)(b.y)
相当于 b.x(b.y)
。
这里还有一个关于内置对象列表的例子:
>>> L = [1, 2, 3, 4]
>>> getattr(a, 'b', L.append)(L[0])
>>> L
[1, 2, 3, 4, 1]
>>>
因为 a
是一个简单的整数,比如 a = 10
,而 'b'
不是 a
的属性,所以 L.append
是通过 getattr
函数返回的,调用 L.append
时,L[0]
的值是 1,这个值被添加到了列表 L 中。
我认为下面的例子会进一步帮助你:
>>> L.append
<built-in method append of list object at 0x7fd34e62c7a0>
>>> getattr(a, 'b', L.append)
<built-in method append of list object at 0x7fd34e62c7a0>
>>>
b.x
是一个包含字符串的属性。没什么特别的,它只是一个变量,而不是你第一个例子中的常量 'b'
。如果把它写成多行的话,可以这样表示:
name = b.x
func = getattr(a, name) # get the function by name
result = func(b.y) # call the function
作者在调用一个函数。下面的内容:
getattr(a, b.x)(b.y)
是从对象 a
中获取一个属性。作者有一个对象 b
,它至少有两个属性,分别是 x
和 y
。他从 a
中获取一个属性,这个属性的名字和 b.x
的值是一样的。这个属性显然是一个函数,他用 b.y
中的值作为参数来调用这个函数。
简化的例子:
>>> class Ex(object):
... def foo(self, val):
... """ b.x has the string "foo", which is the name of this method """
... print val # <-- b.y
...
...
...
>>> class B(object):
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
...
...
>>> a = Ex()
>>> b = B("foo", 1)
>>> getattr(a, b.x)(b.y)
1
在上面的例子中,我们从对象 a
中获取了一个叫 foo
的方法。注意 b.x
的值是 "foo"
。而 b.y
的值是 1
,这个值被作为参数传递给 a.foo()
,也就是 val
。
b
是一个对象,而不是一个字面量。这个代码的作者是在说:“给我获取 a
的一个属性,这个属性的名字是由 b.x
的值决定的,然后用 b.y
的值来调用这个属性。”