【问题标题】:Python - How to fix “ValueError: not enough values to unpack (expected 2, got 1)” [closed]Python - 如何修复“ValueError:没有足够的值来解包(预期 2,得到 1)”[关闭]
【发布时间】:2020-07-15 02:00:03
【问题描述】:

我需要编写一个函数add_to_dict(d, key_value_pairs),它将每个给定的键/值对添加到 python 字典中。参数key_value_pairs 将是(key, value) 形式的元组列表。

该函数应返回所有已更改的键/值对的列表(及其原始值)。

def add_to_dict(d, key_value_pairs):

   newlist = []

   for key,value in d:
       for x,y in key_value_pairs:
           if x == key:
              newlist.append(x,y)
            
   return newlist

我不断收到错误

ValueError: 没有足够的值来解包(预期 2,得到 1)

我该如何解决这个错误?

【问题讨论】:

  • 请添加调用add_to_dict()的脚本
  • for x in dct 不只是遍历键吗?
  • 您能否指出错误发生在哪一行,并以可运行的形式提供您调用该函数的实例。即m.c.v.e
  • d改成d.items()
  • @UlrichSchwarz:是的,确实如此。因此出现错误。

标签: python dictionary


【解决方案1】:

你应该如何调试你的代码

'''
@param d: a dictionary
@param key_value_pairs: a list of tuples in the form `(key, value)`
@return: a list of tuples of key-value-pair updated in the original dictionary
'''
def add_to_dict(d, key_value_pairs):

    newlist = []

    for pair in key_value_pairs:

        # As is mentioned by Mr Patrick
        # you might not want to unpack the key-value-pair instantly
        # to avoid possible corrupted data input from
        # argument `key_value_pairs`
        # if you can't guarantee its integrity
        try:
            x, y = pair
        except (ValueError):
            # unable to unpack tuple
            tuple_length = len(pair)
            raise RuntimeError('''Invalid argument `key_value_pairs`!
                Corrupted key-value-pair has ({}) length!'''.format(tuple_length))

        # Instead of using nesting loop
        # using API would be much more preferable
        v = d.get(x)

        # Check if the key is already in the dictionary `d`
        if v:
            # You probably mean to append a tuple
            # as `array.append(x)` takes only one argument
            # @see: https://docs.python.org/3.7/library/array.html#array.array.append
            #
            # Besides, hereby I quote
            # "The function should return a list of all of the key/value pairs which have changed (with their original values)."
            # Thus instead of using the following line:
            #
            # newlist.append((x, y,))
            #
            # You might want a tuple of (key, old_value, new_value)
            # Hence:
            newlist.append((x, v, y,))

        # I don't know if you want to update the key-value-pair in the dictionary `d`
        # take out the following line if you don't want it
        d[x] = y

    return newlist

如果您想知道如何正确遍历dict 对象,请继续阅读剩余部分。


遍历dict对象的不同方式

Python 3.x

以下部分演示了如何在 Python 3.x 中遍历 dict

迭代键集

for key in d:
    value = d[key]
    print(key, value)

the code segment above has the same effect as the following one:

for key in d.keys():
    value = d[key]
    print(key, value)

迭代一组键值对

for key, value in d.items():
    print(key, value)

迭代值集

for value in d.values():
    print(value)

Python 2.x

以下部分演示了如何在 Python 2.x 中遍历 dict

迭代键集

for key in d:
    value = d[key]
    print(key, value)

keys()返回字典d的键集的列表

for key in d.keys():
    value = d[key]
    print(key, value)

iterkeys()返回字典d的键集的迭代器

for key in d.iterkeys():
    value = d[key]
    print(key, value)

迭代一组键值对

values() 返回字典 d 的键值对集合的列表

for key, value in d.items():
    print(key, value)

itervalues() 返回字典 d 的键值对集的 迭代器

for key, value in d.iteritems():
    print(key, value)

迭代值集

values()返回字典d的值集列表

for value in d.values():
    print(value)

itervalues()返回字典d的值集的迭代器

for value in d.itervalues():
    print(value)

参考:

【讨论】:

    【解决方案2】:

    使用items()解决,比如:

    d = {"foo": "bar"}
    
    for key, value in d.items():
        print key, value
    

    【讨论】:

      【解决方案3】:

      如果您不迭代 dict(包含 100 万个条目)而只迭代 可能 更改的列表并查看它是否更改了 dict 中的任何内容,则可以避免此错误:

      def add_to_dict(d, key_value_pairs):
          """Adds all tuples from key_value_pairs as key:value to dict d, 
          returns list of tuples of keys that got changed as (key, old value)"""
          newlist = []
      
      
          for item in key_value_pairs:
      
              # this handles your possible unpacking errors
              # if your list contains bad data 
              try:
                  key, value = item
              except (TypeError,ValueError):
                  print("Unable to unpack {} into key,value".format(item))
      
              # create entry into dict if needed, else gets existing
              entry = d.setdefault(key,value) 
      
              # if we created it or it is unchanged this won't execute
              if entry != value:
                  # add to list
                  newlist.append( (key, entry) )
                  # change value
                  d[key] = value
      
          return newlist
      
      
      
      d = {}
      print(add_to_dict(d, (  (1,4), (2,5) ) ))    # ok, no change
      print(add_to_dict(d, (  (1,4), (2,5), 3 ) )) # not ok, no changes
      print(add_to_dict(d, (  (1,7), (2,5), 3 ) )) # not ok, 1 change
      

      输出:

      [] # ok
      
      Unable to unpack 3 into key,value
      [] # not ok, no change
      
      Unable to unpack 3 into key,value
      [(1, 4)] # not ok, 1 change
      

      您也可以对您的参数进行一些验证 - 如果任何参数有误,则不会执行任何操作并出现语音错误:

      import collections 
      
      def add_to_dict(d, key_value_pairs):
          """Adds all tuples from key_value_pairs as key:value to dict d, 
          returns list of tuples of keys that got changed as (key, old value)"""
      
          if not isinstance(d,dict):
              raise ValueError("The dictionary input to add_to_dict(dictionary,list of tuples)) is no dict")
      
          if not isinstance(key_value_pairs,collections.Iterable):
              raise ValueError("The list of tuples input to add_to_dict(dictionary,list of tuples)) is no list")  
      
          if len(key_value_pairs) > 0:
              if any(not isinstance(k,tuple) for k in key_value_pairs):
                  raise ValueError("The list of tuples includes 'non tuple' inputs")        
      
              if any(len(k) != 2 for k in key_value_pairs):
                  raise ValueError("The list of tuples includes 'tuple' != 2 elements")        
      
          newlist = []
          for item in key_value_pairs:            
              key, value = item
      
              # create entry into dict if needed, else gets existing
              entry = d.setdefault(key,value) 
      
              # if we created it or it is unchanged this won't execute
              if entry != value:
                  # add to list
                  newlist.append( (key, entry) )
                  # change value
                  d[key] = value
      
          return newlist
      

      所以你会得到更清晰的错误信息:

      add_to_dict({},"tata") 
      # The list of tuples input to add_to_dict(dictionary,list of tuples)) is no list
      
      add_to_dict({},["tata"])
      # The list of tuples includes 'non tuple' inputs
      
      add_to_dict({},[ (1,2,3) ])
      # The list of tuples includes 'tuple' != 2 elements
      
      add_to_dict({},[ (1,2) ])
      # ok
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-28
        • 2021-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-14
        • 2018-04-21
        • 1970-01-01
        相关资源
        最近更新 更多