【问题标题】:'dict_keys' object does not support indexing'dict_keys' 对象不支持索引
【发布时间】:2017-09-20 13:08:11
【问题描述】:

我正在使用 Learn Python the Hard Way 来学习 Python,当我运行以下作为示例提供的代码时,我遇到了 'dict_keys' object does not support indexing error:

import random
from urllib.request import urlopen
import sys

WORD_URL = "http://learncodethehardway.org/words.txt"
WORDS = []

PHRASES = {
    "class %%%(%%%):":
      "Make a class named %%% that is-a %%%.",
    "class %%%(object):\n\tdef __init__(self, ***)" :
      "class %%% has-a __init__ that takes self and *** parameters.",
    "class %%%(object):\n\tdef ***(self, @@@)":
      "class %%% has-a function named *** that takes self and @@@ parameters.",
    "*** = %%%()":
      "Set *** to an instance of class %%%.",
    "***.***(@@@)":
      "From *** get the *** function, and call it with parameters self, @@@.",
    "***.*** = '***'":
      "From *** get the *** attribute and set it to '***'."
}

# do they want to drill phrases first
if len(sys.argv) == 2 and sys.argv[1] == "english":
    PHRASE_FIRST = True
else:
    PHRASE_FIRST = False

# load up the words from the website
for word in urlopen(WORD_URL).readlines():
    WORDS.append(word.strip())


def convert(snippet, phrase):
    class_names = [w.capitalize() for w in
                   random.sample(WORDS, snippet.count("%%%"))]
    other_names = random.sample(WORDS, snippet.count("***"))
    results = []
    param_names = []

    for i in range(0, snippet.count("@@@")):
        param_count = random.randint(1,3)
        param_names.append(', '.join(random.sample(WORDS, param_count)))

    for sentence in snippet, phrase:
        result = sentence[:]

        # fake class names
        for word in class_names:
            result = result.replace("%%%", word, 1)

        # fake other names
        for word in other_names:
            result = result.replace("***", word, 1)

        # fake parameter lists
        for word in param_names:
            result = result.replace("@@@", word, 1)

        results.append(result)

    return results


# keep going until they hit CTRL-D
try:
    while True:
        snippets = PHRASES.keys()
        random.shuffle(snippets)

        for snippet in snippets:
            phrase = PHRASES[snippet]
            question, answer = convert(snippet, phrase)
            if PHRASE_FIRST:
                question = list(answer)
                answer = list(question)

            print(question)

            input("> ")
            print("ANSWER:  %s\n\n" % answer)
except EOFError:
    print("\nBye")

此代码适用于 Python 2.x,而我使用的是 Python 3.5。我看到了以下帖子,但无法将解决方案转换为上述帖子:TypeError: 'dict_keys' object does not support indexing。任何帮助表示赞赏。

【问题讨论】:

  • 您是否愿意接受给出的答案中的答案,以便任何访问您的问题(甚至在访问之前)的人都可以看到问题已解决?

标签: python python-3.x dictionary


【解决方案1】:

尝试替换这个

snippets = PHRASES.keys()

有了这个

snippets = list(PHRASES.keys())

正如您提供的链接中所说,dict.keys() 不会在 python 3 中返回列表。

【讨论】:

    【解决方案2】:

    因此,您需要注意 Python 2.X 和 Python 3.5.x 之间存在一些差异。

    来自@jprokbelly 的答案将帮助您实现目标,但您还需要修改convert 函数中的代码,因为来自urllib.request 的urlopen 将返回字节流而不是字符串,这将导致错误消息:

    TypeError: Can't convert 'bytes' object to str implicitly
    

    因此,如果您想将此代码用于 Python 3.5.x,那么您至少需要做两件事。

    1. 将snippets = PHRASES.keys() 更改为snippets = list(PHRASES.keys()]
    2. 将convert方法的开头改为:

      def convert(snippet, phrase):
          class_names = [w.capitalize() for w in random.sample(WORDS, snippet.count("%%%"))]
          other_names = random.sample(WORDS, snippet.count("***"))
          class_names = [name.decode('UTF-8') for name in class_names]
          other_names = [name.decode('UTF-8') for name in other_names]
      

    您的另一个选择是将您的开发环境设置为使用 virtualenv 并在 Python 2.7.x 中运行代码。

    【讨论】:

      【解决方案3】:

      这里有两个问题(在其他答案中提到),因为 Python 2 和 3 中对字符串/字节类型的不同处理(影响 3 行代码)和对象索引(影响 1 行)。以下运行调整完成后(4行代码)就ok了:

      import random
      from urllib.request import urlopen
      import sys
      
      WORD_URL = "http://learncodethehardway.org/words.txt"
      WORDS = []
      
      PHRASES = {
          "class %%%(%%%):":
            "Make a class named %%% that is-a %%%.",
          "class %%%(object):\n\tdef __init__(self, ***)" :
            "class %%% has-a __init__ that takes self and *** parameters.",
          "class %%%(object):\n\tdef ***(self, @@@)":
            "class %%% has-a function named *** that takes self and @@@ parameters.",
          "*** = %%%()":
            "Set *** to an instance of class %%%.",
          "***.***(@@@)":
            "From *** get the *** function, and call it with parameters self, @@@.",
          "***.*** = '***'":
            "From *** get the *** attribute and set it to '***'."
      }
      
      # do they want to drill phrases first
      if len(sys.argv) == 2 and sys.argv[1] == "english":
          PHRASE_FIRST = True
      else:
          PHRASE_FIRST = False
      
      # load up the words from the website
      for word in urlopen(WORD_URL).readlines():
          WORDS.append(word.strip())
      
      
      def convert(snippet, phrase):
          class_names = [w.capitalize() for w in
                         random.sample(WORDS, snippet.count("%%%"))]
          other_names = random.sample(WORDS, snippet.count("***"))
          results = []
          param_names = []
      
          for i in range(0, snippet.count("@@@")):
              param_count = random.randint(1,3)
              param_names.append(', '.join(random.sample(str(WORDS), param_count)))
      
          for sentence in snippet, phrase:
              result = sentence[:]
              # print(type(result))
      
              # fake class names
              for word in class_names:
                  # print(type(word))
                  result = result.replace("%%%", word.decode("utf-8"), 1)
      
              # fake other names
              for word in other_names:
                  result = result.replace("***", word.decode("utf-8"), 1)
      
              # fake parameter lists
              for word in param_names:
                  result = result.replace("@@@", word.decode("utf-8"), 1)
      
              results.append(result)
      
          return results
      
      
      # keep going until they hit CTRL-D
      try:
          while True:
              for i, item in enumerate(PHRASES.keys()): 
                print(i, "###", item)
      
              snippets = list(PHRASES.keys())
              random.shuffle(snippets)
      
              for snippet in snippets:
                  phrase = PHRASES[snippet]
                  question, answer = convert(snippet, phrase)
                  if PHRASE_FIRST:
                      question = list(answer)
                      answer = list(question)
      
                  print(question)
      
                  input("> ")
                  print("ANSWER:  %s\n\n" % answer)
      except EOFError:
          print("\nBye")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-23
        • 2017-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-23
        • 2019-11-12
        相关资源
        最近更新 更多