This question was already asked here but doesn't contain any answers.
I'm creating a custom class that inherits from the native Python dict
and want to implement some special behavior when an instance of my class is passed to a function with a signature like def foo(*args,**kwargs)
.
According to the docs , the relevant methods that have to be overloaded for this are __iter__
, __getitem__
and __len__
, so I setup a basic example to verify what's happening behind the scenes:
class A(dict):
def __init__(self):
super(A, self).__init__()
def __getattribute__(self, item):
print("__getattribute__ called")
return super(A, self).__getattribute__(item)
def __iter__(self):
print("__iter__ called")
return super(A, self).__iter__()
def __getitem__(self, item):
print("__getitem__ called")
return super(A, self).__getitem__(item)
def __len__(self):
print("__len__ called")
return super(A, self).__len__()
def foo(*args, **kwargs):
print("args: ", args)
print("kwargs: ", kwargs)
a = A()
a['a'] = 1
print("Calling foo() with A")
foo(a)
This just produces the following output:
Calling foo() with A
args: ({'a': 1},)
kwargs: {}
It seems that none of the required functions are being called. I overloaded __getattribute__
additionally, just to check which/any class methods/members are being accessed, but nothing seems to be called. What exactly is happening here? I'm using Python 3.7 if that's relevant.
Well, I came across this question today because I was also searching for that answer. I notice though, that nobody has provided an answer and I could not find any answer online as well! Maybe my GoogleFu is not good enough, maybe it is a simple question, or simply nobody has put the effort to answer it.
Here is the answer then!
Let's define two classes.
A first one that inherits from list
:
class Foo(list):
def __init__(self):
super().__init__()
def __getattribute__(self, item):
print('__getattribute__ called')
return super().__getattribute__(item)
def __iter__(self):
print('__iter__ is called')
return super().__iter__()
def __getitem__(self, item):
print('__getitem__ is called')
return super().__getitem__(item)
def __len__(self):
print('__len__ is called')
return super().__len__()
and a second one that inherits from dict:
class Bar(dict):
def __init__(self):
super().__init__()
def __getattribute__(self, item):
print('__getattribute__ called')
return super().__getattribute__(item)
def __iter__(self):
print('__iter__ is called')
return super().__iter__()
def __getitem__(self, item):
print('__getitem__ is called')
return super().__getitem__(item)
def __len__(self):
print('__len__ is called')
return super().__len__()
Then let's define a function to print a dict:
def bar(a, b):
print(f'a is {a} and b is {b}')
then, let's define our variables:
my_list = Foo()
my_list.extend([1, 2])
my_dict = Bar()
my_dict.update({'a': 1, 'b': 2})
Then, let's see that get's printed!
print(*a)
__iter__ is called
__len__ is called
1 2
and
bar(**b)
__getattribute__ called
__getitem__ is called
__getitem__ is called
a is 1 and b is 2
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.