简体   繁体   English

将星号/双星号应用于 Python 对象时会调用哪些方法?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM