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.
__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.
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.
__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.
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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With