何时使用__getattr__

时间:2012-05-25 21:50:39

标签: python

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

4 个答案:

答案 0 :(得分:8)

一个例子是使用带字典的对象表示法。例如,考虑一个字典

myDict = {'value': 1}

通常在Python中,可以将“value”变量作为

进行访问
myDict['value']

将在Python解释器上打印1。但是,有人可能希望使用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

答案 1 :(得分:3)

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

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

答案 2 :(得分:3)

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

class requests_wrapper():
    client = requests.session(headers={'Authorization':'myauthtoken'})
    base_path = "http://www.example.com"

    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_path + path, **kwargs)

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

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

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

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

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

# Initialize
myclient = requests_wrapper()
# 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

答案 3 :(得分:3)

由于__getattr__only called when an attribute is not found,因此它可以是定义替代地点以查找属性或提供默认值的有用方法,类似于defaultdict

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

还有__getattribute__,它的相关之处在于,只要在对象上查找任何属性,就会调用它。