3

我遇到了__getattr__内置的,想知道什么时候会使用它。我很难从文档
http://docs.python.org/reference/datamodel.html#中考虑实际用途。什么是它如何在代码中使用和有用的实际示例?

4

4 回答 4

9

一个例子是将对象表示法与字典一起使用。例如,考虑一个字典

myDict = {'value': 1}

通常在 Python 中访问“值”变量为

myDict['value']

它将1在 Python 解释器上打印。然而,人们可能希望使用该myDict.value符号。这可以通过使用以下类来实现:

class DictAsMember(dict):
    def __getattr__(self, name):
        value = self[name]
        if isinstance(value, dict):
            value = DictAsMember(value)
        return value

my_dict = DictAsMember()
my_dict['property'] = {'sub_property': 1}

print(my_dict.property.sub_property) # 1 will be printed
于 2012-05-25T22:09:08.147 回答
3

一个示例用法是围绕某个对象创建一个简单的包装器。例如,为了记录调用或修改其行为而不继承它,也不必实现对象的整个接口。

那里有几个很好的记录示例,例如http://western-skies.blogspot.fr/2008/02/complete-example-of-getattr-in-python.html

于 2012-05-25T21:53:25.860 回答
3

由于__getattr__在未找到属性时调用,因此它可能是一种有用的方法来定义查找属性的备用位置,或提供默认值,类似于defaultdict.

您还可以通过将此处的所有查找委托给另一个对象来模拟比对象的 MRO 中的所有其他基类更高的基类(尽管这样做,如果另一个对象将属性委托回,您可能会出现无限循环)。

还有__getattribute__, 相关的任何时候在对象上查找任何属性时都会调用它。

于 2012-05-25T22:10:53.230 回答
2

编辑:这是关于内置函数getattr,而不是__getattr__方法。

我需要为使用不记名令牌的 REST 客户端执行此操作。我将Requests的 Session 对象包装到我自己的界面中,这样我就可以始终发送 auth 标头,并且(更相关地)仅使用 URL 的路径向同一个站点发出 HTTP 请求。

class RequestsWrapper():
    def __init__(self, base_url):
        self.client = requests.Session(
            headers={'Authorization':'myauthtoken'}
        )
        self.base_url = base_url

    def _make_path_request(self, http_method, path, **kwargs):
        """
        Use the http_method string to find the requests.Session instance's
        method.
        """
        method_to_call = getattr(self.client, http_method.lower())
        return method_to_call(self.base_url + path, **kwargs)

    def path_get(self, path, **kwargs):
        """ 
        Sends a GET request to base_url + path.
        """
        return self._make_path_request('get', path, **kwargs)

    def path_post(self, path, **kwargs):
        """ 
        Sends a POST request to base_url + path.
        """
        return self._make_path_request('post', path, **kwargs)

    def path_put(self, path, **kwargs):
        """ 
        Sends a PUT request to base_url + path.
        """
        return self._make_path_request('put', path, **kwargs)

    def path_delete(self, path, **kwargs):
        """ 
        Sends a DELETE request to base_url + path.
        """
        return self._make_path_request('delete', path, **kwargs)

然后,我可以根据路径发出请求:

# Initialize
myclient = RequestsWrapper("http://www.example.com")
# Make a get request to http://www.example.com/api/spam/eggs
response = myclient.path_get("/api/spam/eggs")
# Print the response JSON data
if response.ok:
    print response.json
于 2012-05-25T22:09:07.213 回答