【问题标题】:Function with dictionaries as optional arguments - Python以字典作为可选参数的函数 - Python
【发布时间】:2016-03-19 00:09:41
【问题描述】:

我正在尝试创建一个可以接收多个或几个字典作为输入的函数。我正在使用以下代码:

def merge_many_dics(dic1,dic2,dic3=True,dic4=True,dic5=True,dic6=True,dic7=True,dic8=True,dic9=True,dic10=True):
"""
Merging up to 10 dictionaries with same keys and different values
:return: a dictionary containing the common dates as keys and both values as values
"""
manydics = {}
for k in dic1.viewkeys() & dic2.viewkeys() & dic3.viewkeys() & dic4.viewkeys() & dic5.viewkeys() & dic6.viewkeys()\
        & dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
    manydics[k] = (dic1[k], dic2[k],dic3[k],dic4[k],dic5[k],dic6[k],dic7[k],dic8[k],dic9[k],dic10[k])

return manydics

请注意,我试图将参数 dic3、dic4、dic5 等设为“True”,因此当未指定它们并在函数中调用它们时,不会发生任何事情。但是我收到以下错误:

Traceback (most recent call last):
File "/Users/File.py", line 616, in <module>
main_dic=merge_many_dics(dic1,dic2,dic3,dic4)
File "/Users/File.py", line 132, in merge_many_dics
& dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
AttributeError: 'bool' object has no attribute 'viewkeys'

有没有人可以启发我的旅程?

【问题讨论】:

    标签: python dictionary optional-arguments


    【解决方案1】:

    你应该试试 args 语法:

    def merge_many_dics(*args):
       iterate over your args to join them
    

    然后您可以使用任意数量的参数调用该函数。

    带有 *args 的函数可能如下:

       def print_all(name, *args):
          print "Hello", name, "here are your args"
          for arg in args:
             print arg
    
       print_all("Claus", "car", "boat", "house")
    

    这将打印:

    Hello Clause here are your args
    
    car
    boat
    house
    

    【讨论】:

    • 它是如何工作的?没用过*args,能再解释一下吗?
    • args 是传递给函数的所有参数的列表。当您事先不知道会收到多少个参数时,您可以使用它。
    • 我做到了,并为函数定义了 4 个字典。结果我收到了这个错误:NameError: global name 'dic5' is not defined。差距在哪里?
    • 你将把你的字典放在一个数组中(即 args)遍历 args 以访问传递的单个字典
    • 你能写一个迭代函数中的args的例子吗?
    【解决方案2】:

    正如错误所说,您无法查看布尔值的键,也就是 True.viewkeys() 不起作用。将您的默认字典更改为空,离开:

    def merge_many_dics(dic1,dic2,dic3={},dic4={},dic5={},dic6={},dic7={},dic8={},dic9={},dic10={}):
        """
        Merging up to 10 dictionaries with same keys and different values
        :return: a dictionary containing the common dates as keys and both values as values
        """
        manydics = {}
        for k in dic1.viewkeys() & dic2.viewkeys() & dic3.viewkeys() & dic4.viewkeys() & dic5.viewkeys() & dic6.viewkeys()\
                & dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
            manydics[k] = (dic1[k], dic2[k],dic3[k],dic4[k],dic5[k],dic6[k],dic7[k],dic8[k],dic9[k],dic10[k])
    
        return manydics
    

    这是一个实现,其中您为每个键创建一个列表并添加每个项目,我相信它可以进行更多优化,但它非常可读:

    def merge_many_dicts(*args):
        """
        Merging all dictionaries suposing all dictionaries share keys
        :return: a dictionary containing the common dates as keys and both values as values
        """
        manydicts = {}
        for k in args:
            for key in k.iterkeys():
                manydicts[key] = []
        for k in args:
            for key, value in k.iteritems():
                manydicts[key].append(value)
    
        return manydicts
    

    【讨论】:

    • 它可以工作,但该函数将返回一个空字典,这不是本意
    • 我会使用 *args 方法,我会编辑我的答案
    • 永远不要使用可变的默认值。请参阅pythonconquerstheuniverse.wordpress.com/2012/02/15/… 而不是使用*args 或使用 None 作为默认值。
    • @abutremutante 如果你使用None 方法,你应该在函数内部检查参数是否被传递。例如,使用if dic3 is Noneif isinstance(dic3, dict)。但最好使用*args,如另一个答案中所述。
    • @DeepSpace:如您的链接所述,可变默认值在正确使用时非常有用。但是,我当然同意它们应该用于这样的事情。由于您的链接和“Least Astonishment” in Python: The Mutable Default Argument 中提到的问题,当您使用可变默认参数时,明确评论您正在做的事情是一个好主意。
    【解决方案3】:

    使用arbitrary argument list,可以使用任意数量的参数调用该函数:

    >>> def merge_many_dics(*dicts):
    ...     common_keys = reduce(lambda a, b: a & b, (d.viewkeys() for d in dicts))
    ...     return {key: tuple(d[key] for d in dicts) for key in common_keys}
    ...
    >>> merge_many_dics({1:2}, {1:3}, {1:4, 2:5})
    {1: (2, 3, 4)}
    

    【讨论】:

    • FWIW,operator.and_lambda 的替代品
    【解决方案4】:

    您可以使用以下代码,在函数中初始化这些参数

    def merge_many_dics(dic1, dic2, dic3=None, dic4=None, dic5=None, dic6=None, dic7=None, dic8=None, dic9=None,
                        dic10=None):
        """
        Merging up to 10 dictionaries with same keys and different values
        :return: a dictionary containing the common dates as keys and both values as values
        """
        for item in locals().items():
            if item is None:
                item = dic1
    
        manydics = {}
        for k in dic1.viewkeys() & dic2.viewkeys() & dic3.viewkeys() & dic4.viewkeys() & dic5.viewkeys() & dic6.viewkeys() \
                & dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
            manydics[k] = (dic1[k], dic2[k], dic3[k], dic4[k], dic5[k], dic6[k], dic7[k], dic8[k], dic9[k], dic10[k])
    
        return manydics
    

    【讨论】:

      【解决方案5】:

      这是基于@falsetru 答案并使用operator.and_ 函数的Python 3.x 答案。

      >>> from functools import reduce
      >>> import operator
      >>> def merge_many_dicts(*dicts):
      ...     common_keys = reduce(operator.and_, (d.keys() for d in dicts))
      ...     return {key: tuple(d[key] for d in dicts) for key in common_keys}
      ... 
      >>> merge_many_dicts({1:2}, {1:3}, {1:4, 2:5})
      {1: (2, 3, 4)}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-15
        • 1970-01-01
        • 1970-01-01
        • 2015-02-28
        • 1970-01-01
        • 2018-08-14
        • 1970-01-01
        • 2013-07-18
        相关资源
        最近更新 更多