When to use __getattr__

I came across the built-in __getattr__ and wondered when it would be used. It was hard for me to think about the practical use of the documentation http://docs.python.org/reference/datamodel.html# . What will be the actual example of how it can be used and useful in the code?

+1
source share
4 answers

One example is the use of object notation with dictionaries. For example, consider a dictionary

 myDict = {'value': 1} 

Usually in Python the variable 'value' is opened as

 myDict['value'] 

which will print 1 in the Python interpreter. However, you can use the notation myDict.value . This can be achieved using the following class:

 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 
+6
source

An example of use would be to create a simple wrapper around some object. In order, for example, to register calls or change their behavior without inheriting from it, and without having to implement the entire interface of the object.

There are some good documented examples, for example, http://western-skies.blogspot.fr/2008/02/complete-example-of-getattr-in-python.html .

+3
source

I needed to do this for a REST client using media tokens. I wrapped the Requests session object in my own interface so that I can always send the auth header and (more relevant) make HTTP requests to the same site, just using the URL.

 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) 

Then I could just make a request based on the path:

 # 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
source

Since __getattr__ is called only when the attribute is not found , it can be a useful way to determine an alternative location to search for an attribute or enter default values ​​similar to defaultdict .

You can also emulate the base class above all the others in the MRO object, delegating all search queries here to another object (although you could have an infinite loop if another object delegates the attribute back).

There is also __getattribute__ , associated with the fact that it is called at any time when any attribute is viewed on the object.

+3
source

Source: https://habr.com/ru/post/918170/


All Articles