[英]Which methods are called when an asterisk/double asterisk is applied to a Python object?
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)
.我正在创建一个继承自本机 Python dict
的自定义类,并希望在将我的类的实例传递给具有像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:根据docs ,必须为此重载的相关方法是__iter__
、 __getitem__
和__len__
,因此我设置了一个基本示例来验证幕后发生的事情:
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.我另外重载了__getattribute__
,只是为了检查正在访问哪些/任何类方法/成员,但似乎没有调用任何内容。 What exactly is happening here?这里到底发生了什么? I'm using Python 3.7 if that's relevant.如果相关,我正在使用 Python 3.7。
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.也许我的 GoogleFu 不够好,也许是一个简单的问题,或者只是没有人努力回答它。
Here is the answer then!那么答案就在这里!
Let's define two classes.让我们定义两个类。
A first one that inherits from list
:第一个继承自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:和从 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!然后,让我们看看 get 的打印结果!
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.