python的** kwargs效率

时间:2018-02-22 08:47:28

标签: python python-3.x dictionary avro kwargs

这样构建python3流程没问题吗?

def foo(**kwargs):
    kwargs['kw'] = 1
    return bar(**kwargs, wk=2)
def bar(**kwargs):
    process(1,2,'sss',**kwargs)
    for i in kwargs:
        print(i)
...etc...

kwargs是否会使用单个可变对象(dict),只有它的引用才能传递给流程,或者我会一遍又一遍地解压缩并创建?

更准确的问题。如果我这样做:

def a(**kwargs):
    return b(**kwargs)
def b(**kwargs):
    return c(**kwargs)
...
def z(**kwargs):
    print(**kwargs)

一次只会有1个字典吗?如果是这样,每次调用都会创建新对象吗? 或者我会堆叠它们吗?

实际情况是我是与AVRO通信的子服务之一。所以我有一个包将该二进制文件转换为dict,然后我需要做一些事情并创建一个新的AVRO。

新架构中不存在某些字段,有些字段已添加,有些字段只是在不触及它们的情况下传递。

所以我只是拿了第一个dict,一遍遍地传递越来越多的数据然后在最后我有另一个模式,avro包可以采用如此庞大的dict并仅序列化模式中定义的内容。

这种方法可以吗?

3 个答案:

答案 0 :(得分:5)

为每个函数中的每个**kwargs参数构建一个新字典。这是因为调用 **kwargs语法与函数签名中的语法不同

  • 在调用中使用**kwargs会导致将字典解压缩为单独的关键字参数。
  • 使用**kwargs作为catch-all参数会导致字典从传入的关键字参数生成

即使不是这种情况,Python也无法通过共享字典进行优化。调用foo()的函数bar()必须处理传入调用的字典kwargs可能会发生变异的可能性。

所以,不,在一系列连接函数中使用**kwargs不会提高效率。

快速演示,表明字典传递给一系列函数是不同的:

>>> def a(**kwargs):
...     print('a', id(kwargs))
...     b(**kwargs)
...
>>> def b(**kwargs):
...     print('b', id(kwargs))
...
>>> a(foo='bar')
a 4556474552
b 4557517304

如果共享词典,他们的id()值也会相同。

如果要在函数之间传递共享状态,请明确执行此操作。直接传递字典,例如:

def foo(**state):
    state['kw'] = 1
    state['wk'] = 2
    return bar(state)  # kwargs passed in as a single argument

def bar(state):
    # etc.

答案 1 :(得分:0)

很容易找到直接发生的事情:

def a(**kwargs):
    b(**kwargs)
    print(kwargs)  # prints {'x': 1}, not {'x': 1, 'y': 2}

def b(**kwargs):
    kwargs['y'] = 2

a(x=1)

所以每次都有一个新的词典。

答案 2 :(得分:0)

为了记录,我真的很喜欢Martijn的回答。要按照我认为您的意图回答您的问题,您需要跳过**,因为Martijn说;

def a(some_dict):
    # do some operations on this dict
    b(some_dict)

def b(some_dict):
    # do some more operations on this dict
    c(some_dict)

def c(some_dict):
    # you know how this goes by know, don't you?

# Careful thing to note here: you do not need to reassign here,
# since each function are dealing with a reference to the same
# original object, there is no need to pass it back when we are
# done.

a(some_dict)

为了进一步增加,这在我认为是工厂模式中很常见;

class CookLasagna:
    def __init__(self, lasagna=None):
        self.lasagna = lasagna
        self.build()

    def build(self):
        self.preheat_oven()
        self.cook_minced_meat()
        self.soak_pasta()
        self.layer()

    def preheat_oven(self):
        # preheat the oven with lasagna object reference

    def cook_minced_meat(self):
        # cook minced meat with lasagna object reference

    def soak_pasta(self):
        # soak pasta with lasagna object reference

    def layer(self):
        # layer with lasagna object reference