python';s**kwargs效率

python';s**kwargs效率,python,python-3.x,dictionary,avro,keyword-argument,Python,Python 3.x,Dictionary,Avro,Keyword Argument,像这样构建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),并且只有它的引用将在流中传递,还是我将被解包并一次又一次地创建 更精确的问题。

像这样构建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)
一次只能有一个dict吗?如果是这样,每次调用都会创建新对象吗? 还是我要把它们叠起来

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

有些字段在新模式中不存在,有些字段已添加,有些字段只是传递而未触及它们

所以我只是拿了第一个dict,一遍又一遍地传递它,添加越来越多的数据,最后我有了另一个模式,avro包可以拿这么大的dict,只序列化模式中定义的内容


这种方法行吗?

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

  • 在调用中使用
    **kwargs
    会导致将字典解压为单独的关键字参数
  • 使用
    **kwargs
    作为catch-all参数会根据传入的关键字参数生成字典
即使不是这样,Python也无法通过共享字典来优化。函数
foo()
调用
bar()

因此,不,在一系列连接的函数中使用
**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.

很容易直接发现发生了什么:

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

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

a(x=1)

所以每次都有一个新的口述。

记录在案,我真的很喜欢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

一般来说,这种方法与我对编程的理解背道而驰,但如果你想做的只是改变这条指令,我真的不明白为什么不……不,我想创建一个好的代码。问题是,我希望最小化模式更改时需要完成的工作,并且代码本身看起来与模式没有很强的相关性。你会怎么做?如果你想这样做,为什么你不直接传递一个dict并使参数显式化?因为在链的顶端是通过kwargs传递一些参数的东西,我想我可以用这个dict来代替新的dict,这正是我害怕的,如果我把这些都封装在一个类中,用dict创建一个字段,并在我想要的任何地方修改它?@Kazz:是的,你总是可以传递一个普通字典或自定义可变对象。这不是我问的问题。你问“一次只能有一个dict吗?”@Kazz你能解释一下为什么吗?也许我不清楚。如果有一个dict被传递,那么
a
将打印出
{'x':1,'y':2}
。我说的是链接调用,比如
a(b(c(d(…))
。当然,在您的代码中,当调用
b
a
未完成,因此它将进入堆栈,稍后返回到堆栈。好的,我想我不清楚。我的意思是20个电话之后会有20条短信吗?哈哈,这正是我需要的。我需要阅读更多关于代码模式的内容