我最近使用了read about the getattr()
function。问题是我仍然不能掌握它的用法。我对getattr()
唯一的理解是,getattr(li, "pop")
和调用li.pop
是一样的。
我不理解书中提到的如何使用它来获得对函数的引用,直到运行时才知道它的名称。也许这就是我在编程方面的新手。有没有人能说明一下这个问题?我到底应该在什么时候以及如何使用它?
发布于 2010-11-02 16:48:21
Python中的对象可以有属性--数据属性和使用这些属性的函数(方法)。实际上,每个对象都有内置属性(可以在Python控制台中尝试使用dir(None)
、dir(True)
、dir(...)
、dir(dir)
)。
例如,您有一个对象person
,它有几个属性:name
、gender
等。
您可以访问这些属性(可以是方法或数据对象),通常可以这样写:person.name
、person.gender
、person.the_method()
等。
但是,如果您在编写程序时不知道属性的名称,该怎么办?例如,属性的名称存储在一个名为attr_name
的变量中。
如果
attr_name = 'gender'
然后,不是写
gender = person.gender
你可以写
gender = getattr(person, attr_name)
一些实践:
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
>>> class Person():
... name = 'Victor'
... def say(self, what):
... print(self.name, what)
...
>>> getattr(Person, 'name')
'Victor'
>>> attr_name = 'name'
>>> person = Person()
>>> getattr(person, attr_name)
'Victor'
>>> getattr(person, 'say')('Hello')
Victor Hello
如果对象中不存在具有给定名称的属性,则getattr
将引发AttributeError
:
>>> getattr(person, 'age')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'
但是您可以传递一个默认值作为第三个参数,如果该属性不存在,则会返回该参数:
>>> getattr(person, 'age', 0)
0
您可以结合使用getattr
和dir
来遍历所有属性名称并获取它们的值:
>>> dir(1000)
['__abs__', '__add__', ..., '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
>>> obj = 1000
>>> for attr_name in dir(obj):
... attr_value = getattr(obj, attr_name)
... print(attr_name, attr_value, callable(attr_value))
...
__abs__ <method-wrapper '__abs__' of int object at 0x7f4e927c2f90> True
...
bit_length <built-in method bit_length of int object at 0x7f4e927c2f90> True
...
>>> getattr(1000, 'bit_length')()
10
这样做的一个实际用途是查找名称以test
和call them开头的所有方法。
与getattr
类似,还有setattr
,它允许您设置具有其名称的对象的属性:
>>> setattr(person, 'name', 'Andrew')
>>> person.name # accessing instance attribute
'Andrew'
>>> Person.name # accessing class attribute
'Victor'
>>>
发布于 2010-11-02 16:32:54
getattr
的一个非常常见的用例是将数据映射到函数。
例如,在像Django或Pylons这样的web框架中,getattr
使得将web请求的URL映射到将要处理它的函数变得简单。举个例子,如果你仔细看一下Pylons的路由,你会发现(至少在默认情况下)它会砍掉一个请求的URL,比如:
http://www.example.com/customers/list
分成“客户”和“列表”。然后,它搜索一个名为CustomerController
的控制器类。假设它找到了这个类,它会创建这个类的一个实例,然后使用getattr
来获取它的list
方法。然后,它调用该方法,将请求作为参数传递给它。
一旦掌握了这个概念,扩展web应用程序的功能就变得非常容易:只需向控制器类添加新方法,然后在页面中创建使用这些方法的适当URL的链接。所有这些都是由getattr
实现的。
发布于 2010-11-02 15:02:26
下面是一个简单明了的示例,说明一个类如何根据使用getattr()
执行保存方法的操作系统来触发不同版本的保存方法。
import os
class Log(object):
def __init__(self):
self.os = os.name
def __getattr__(self, name):
""" look for a 'save' attribute, or just
return whatever attribute was specified """
if name == 'save':
try:
# try to dynamically return a save
# method appropriate for the user's system
return getattr(self, self.os)
except:
# bail and try to return
# a default save method
return getattr(self, '_save')
else:
return getattr(self, name)
# each of these methods could have save logic specific to
# the system on which the script is executed
def posix(self): print 'saving on a posix machine'
def nt(self): print 'saving on an nt machine'
def os2(self): print 'saving on an os2 machine'
def ce(self): print 'saving on a ce machine'
def java(self): print 'saving on a java machine'
def riscos(self): print 'saving on a riscos machine'
def _save(self): print 'saving on an unknown operating system'
def which_os(self): print os.name
现在让我们在一个示例中使用这个类:
logger = Log()
# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along
# somewhere else as 1st class:
save_func()
# or you can just call it directly:
logger.save()
# other attributes will hit the else
# statement and still work as expected
logger.which_os()
https://stackoverflow.com/questions/4075190
复制相似问题