【问题标题】:When to use __getattr__何时使用 __getattr__
【发布时间】:2012-06-01 11:18:01
【问题描述】:

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

【问题讨论】:

    标签: python


    【解决方案1】:

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

    myDict = {'value': 1}
    

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

    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
    

    【讨论】:

    • 应该是value = self[name]
    • @Darthfett 是的,感谢您发现这一点 - 我已经更正了示例代码。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      由于__getattr__only called when an attribute is not found,它可以是一种有用的方法来定义查找属性的备用位置,或提供默认值,类似于defaultdict

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

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

      【讨论】:

        【解决方案4】:

        编辑:这是关于内置函数 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
        

        【讨论】:

        • 我认为这个答案解决了相反的问题:为什么有人会使用 getattr() 内置函数。我理解这个问题是关于为什么一个类会提供一个__getattr__() 魔术方法。
        • @BrandonRhodes 呵呵,你说得对。哎呀,这段代码太糟糕了,是时候进行死灵编辑了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-27
        • 2015-07-17
        • 2011-06-10
        相关资源
        最近更新 更多