Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: how to implement __getattr__()?

Tags:

python

My class has a dict, for example:

class MyClass(object):     def __init__(self):         self.data = {'a': 'v1', 'b': 'v2'} 

Then I want to use the dict's key with MyClass instance to access the dict, for example:

ob = MyClass() v = ob.a   # Here I expect ob.a returns 'v1' 

I know this should be implemented by __getattr__, but I'm new to Python, I don't exactly know how to implement it.

like image 705
TieDad Avatar asked Apr 26 '13 13:04

TieDad


People also ask

What does __ Getattr __ do in Python?

__getattr__Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self ). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.

How do I get attr in Python?

Python getattr() function. Python getattr() function is used to get the value of an object's attribute and if no attribute of that object is found, default value is returned. Basically, returning the default value is the main reason why you may need to use Python getattr() function.

What is __ slots __ in Python?

__slots__ is a class variable. If you have more than one instance of your class, any change made to __slots__ will show up in every instance. You cannot access the memory allocated by the __slots__ declaration by using subscription. You will get only what is currently stored in the list.


Video Answer


1 Answers

class MyClass(object):      def __init__(self):         self.data = {'a': 'v1', 'b': 'v2'}      def __getattr__(self, attr):         return self.data[attr] 

>>> ob = MyClass() >>> v = ob.a >>> v 'v1' 

Be careful when implementing __setattr__ though, you will need to make a few modifications:

class MyClass(object):      def __init__(self):         # prevents infinite recursion from self.data = {'a': 'v1', 'b': 'v2'}         # as now we have __setattr__, which will call __getattr__ when the line         # self.data[k] tries to access self.data, won't find it in the instance          # dictionary and return self.data[k] will in turn call __getattr__         # for the same reason and so on.... so we manually set data initially         super(MyClass, self).__setattr__('data', {'a': 'v1', 'b': 'v2'})      def __setattr__(self, k, v):         self.data[k] = v      def __getattr__(self, k):         # we don't need a special call to super here because getattr is only          # called when an attribute is NOT found in the instance's dictionary         try:             return self.data[k]         except KeyError:             raise AttributeError 

>>> ob = MyClass() >>> ob.c = 1 >>> ob.c 1 

If you don't need to set attributes just use a namedtuple eg.

>>> from collections import namedtuple >>> MyClass = namedtuple("MyClass", ["a", "b"]) >>> ob = MyClass(a=1, b=2) >>> ob.a 1 

If you want the default arguments you can just write a wrapper class around it:

class MyClass(namedtuple("MyClass", ["a", "b"])):      def __new__(cls, a="v1", b="v2"):         return super(MyClass, cls).__new__(cls, a, b) 

or maybe it looks nicer as a function:

def MyClass(a="v1", b="v2", cls=namedtuple("MyClass", ["a", "b"])):     return cls(a, b) 

>>> ob = MyClass() >>> ob.a 'v1' 
like image 90
jamylak Avatar answered Sep 21 '22 01:09

jamylak