【问题标题】:Python: Cast Dictionary to Tuple implicit by calling a methodPython:通过调用方法将字典转换为隐式元组
【发布时间】:2018-06-06 15:41:48
【问题描述】:

我对 Mininet 开源项目中的代码有疑问。我将其抽象为以下场景:

def bar (*a, **b):
    b.update({'a':(a,)})
    foo(**b)

def foo (*a, **c):
    print(c)
    print(a)

if __name__ == '__main__':
    bar(2,3,4, x=3, y=5)

方法 bar 只是创建 foo 的函数调用的助手。 如果我运行它, print(a) 没有输出,因为值仍然存储在字典 b 中。如果我将 *a 更改为 a,它可以正常工作。

这是我的问题: 是否有可能不修改将数据放入 *a 和数据的方法 foo 并且 foo 的调用就像在第 3 行中一样?这意味着只允许修改方法栏中的b。

【问题讨论】:

  • 你可以这样做def bar(*a, **b): foo(a=a, **b)

标签: python dictionary tuples optional-parameters optional-arguments


【解决方案1】:

我认为不可能同时满足您的两个条件。

如果方法foo 保持不变,则参数*a 表示一个列表 没有名称的参数(如您的示例中的bar(2,3,4))。第 3 行中对foo(**b) 的调用意味着传递关键字参数(如您的示例中的bar(x=3, y=5)),因此它们将被传递给**c,因为它是foo 中的关键字参数。

【讨论】:

    【解决方案2】:

    好的,所以我想让你理解而不是仅仅给出答案,因为 StackOverflow 是关于解释概念而不是编写代码,让我们理解几点:

    *args 和 **kwargs 用作任意数量的参数。

    Kwargs ** 语法需要一个映射(比如字典);每个 映射中的键值对成为关键字参数。

    *args 接收一个包含位置参数的元组。

    现在让我们举个简单的例子来理解你的问题:

    def check(*a,**b):
        print(a)
        print(b)
    

    现在 *a 需要元组或列表或位置参数,而 **b 需要字典格式的关键字参数。

    在进入问题之前还有一点:

    *l 习惯用法是解包参数列表、元组、集合

    a,*b=(1,2,3,4,5)
    print(a)
    print(b)
    

    输出:

    1
    [2, 3, 4, 5]
    

    现在,如果我将该函数称为:

    def check(*a,**b):
        print("value_a {}".format(a))
        print("value_b {}".format(b))
    
    
    print(check({'y': 5, 'x': 3, 'a': 5,'r':56}))
    

    现在 *a 将采用该值,因为没有关键字参数:

    value_a ({'x': 3, 'y': 5, 'a': 5, 'r': 56},)
    

    但是让我们添加一些关键字参数:

    print(check({'y': 5, 'x': 3, 'a': 5,'r':56},key_s=5,values=10))
    

    输出:

    value_a ({'a': 5, 'y': 5, 'r': 56, 'x': 3},)
    value_b {'key_s': 5, 'values': 10}
    

    让我们开始使用 unpack 方法:

    print(check(*{'y': 5, 'x': 3, 'a': 5,'r':56}))
    

    输出将是:

    value_a ('r', 'x', 'y', 'a')
    value_b {}
    None
    

    因为正如我所展示的,* 将解包 dict 的键,并将它们视为位置参数而不是关键字参数。

    现在让我们使用 ** 解包,它将 dict 解包为键值对:

    我想你明白了,现在让我们使用 ** 来映射字典,这样它将解压字典和每个键,值将是关键字参数:

    print(check(**{'y': 5, 'x': 3, 'a': 5,'r':56}))
    

    输出:

    value_a ()
    value_b {'y': 5, 'r': 56, 'a': 5, 'x': 3}
    

    所以我想现在一切都清楚了。

    现在让我们回到您的问题:

    如你所说,如果你正在使用:

    def check(a,**b):
        print("value_a {}".format(a))
        print("value_b {}".format(b))
    
    
    print(check(**{'y': 5, 'x': 3, 'a': 5,'r':56}))
    

    您得到结果是因为它从 dict 获取“a”值,而其余值由 **b 获取

    现在如果你想使用 *a 和 **b 那么你必须提供:

    the positional argument for *a
    Keyworded argument for **b
    

    正如你所说你不想修改 foo 那么你可以尝试这样的事情:

    def bar (*a, **b):
        foo((a,),**b)
    
    
    def foo (*a, **c):
        print(c)
        print(a)
    
    if __name__ == '__main__':
        bar(2,3,4, x=3, y=5)
    

    输出:

    {'y': 5, 'x': 3}
    (((2, 3, 4),),)
    

    【讨论】:

    • 感谢您的回答;我完全确认你的介绍。感谢那。我的问题是第二个条件: foo(**b) 不应该改变这也可能吗
    猜你喜欢
    • 2020-10-03
    • 2022-07-24
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 2011-04-03
    相关资源
    最近更新 更多