首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >getattr()到底是什么,我该如何使用它?

getattr()到底是什么,我该如何使用它?
EN

Stack Overflow用户
提问于 2010-11-02 13:45:12
回答 10查看 304.8K关注 0票数 359

我最近使用了read about the getattr() function。问题是我仍然不能掌握它的用法。我对getattr()唯一的理解是,getattr(li, "pop")和调用li.pop是一样的。

我不理解书中提到的如何使用它来获得对函数的引用,直到运行时才知道它的名称。也许这就是我在编程方面的新手。有没有人能说明一下这个问题?我到底应该在什么时候以及如何使用它?

EN

回答 10

Stack Overflow用户

发布于 2010-11-02 16:48:21

Python中的对象可以有属性--数据属性和使用这些属性的函数(方法)。实际上,每个对象都有内置属性(可以在Python控制台中尝试使用dir(None)dir(True)dir(...)dir(dir) )。

例如,您有一个对象person,它有几个属性:namegender等。

您可以访问这些属性(可以是方法或数据对象),通常可以这样写:person.nameperson.genderperson.the_method()等。

但是,如果您在编写程序时不知道属性的名称,该怎么办?例如,属性的名称存储在一个名为attr_name的变量中。

如果

代码语言:javascript
复制
attr_name = 'gender'

然后,不是写

代码语言:javascript
复制
gender = person.gender

你可以写

代码语言:javascript
复制
gender = getattr(person, attr_name)

一些实践:

代码语言:javascript
复制
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

代码语言:javascript
复制
>>> getattr(person, 'age')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'

但是您可以传递一个默认值作为第三个参数,如果该属性不存在,则会返回该参数:

代码语言:javascript
复制
>>> getattr(person, 'age', 0)
0

您可以结合使用getattrdir来遍历所有属性名称并获取它们的值:

代码语言:javascript
复制
>>> 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

这样做的一个实际用途是查找名称以testcall them开头的所有方法。

getattr类似,还有setattr,它允许您设置具有其名称的对象的属性:

代码语言:javascript
复制
>>> setattr(person, 'name', 'Andrew')
>>> person.name  # accessing instance attribute
'Andrew'
>>> Person.name  # accessing class attribute
'Victor'
>>>
票数 324
EN

Stack Overflow用户

发布于 2010-11-02 16:32:54

getattr的一个非常常见的用例是将数据映射到函数。

例如,在像Django或Pylons这样的web框架中,getattr使得将web请求的URL映射到将要处理它的函数变得简单。举个例子,如果你仔细看一下Pylons的路由,你会发现(至少在默认情况下)它会砍掉一个请求的URL,比如:

代码语言:javascript
复制
http://www.example.com/customers/list

分成“客户”和“列表”。然后,它搜索一个名为CustomerController的控制器类。假设它找到了这个类,它会创建这个类的一个实例,然后使用getattr来获取它的list方法。然后,它调用该方法,将请求作为参数传递给它。

一旦掌握了这个概念,扩展web应用程序的功能就变得非常容易:只需向控制器类添加新方法,然后在页面中创建使用这些方法的适当URL的链接。所有这些都是由getattr实现的。

票数 45
EN

Stack Overflow用户

发布于 2010-11-02 15:02:26

下面是一个简单明了的示例,说明一个类如何根据使用getattr()执行保存方法的操作系统来触发不同版本的保存方法。

代码语言:javascript
复制
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

现在让我们在一个示例中使用这个类:

代码语言:javascript
复制
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()
票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4075190

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档