"dict" об'єкт не має атрибута "has_key"


105

Під час обходу графіка в Python, я отримую цю помилку:

"dict" об'єкт не має атрибута "has_key"

Ось мій код:

def find_path(graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return path
    if not graph.has_key(start):
        return None
    for node in graph[start]:
        if node not in path:
            newpath = find_path(graph, node, end, path)
            if newpath: return newpath
    return None

Код спрямований на пошук шляхів від одного вузла до іншого. Джерело коду: http://cs.mwsu.edu/~terry/courses/4883/lectures/graphs.html

Чому я отримую цю помилку і як я можу її виправити?


2
if not start in graph:
Пітер Вуд,

1
Можливий дублікат 'has_key ()' або 'in'?
Пітер Вуд,

Відповіді:


180

has_keyбуло видалено в Python 3. З документації :

  • Видалено dict.has_key()- inзамість цього використовуйте оператор.

Ось приклад:

if start not in graph:
    return None

1
Я думаю, що key not in d.keys()це, мабуть, набагато повільніше, оскільки key not in dмає бути пошук O (1), і я вважаю keys, що складається список, який є O (n) пошуку (не кажучи вже про зайве місце в пам'яті). Хоча я можу помилитися в цьому - можливо, це все одно буде хешований пошук
Адам Сміт

3
@AdamSmith не в Python 3 d.keys()- це подання, яке реалізує більшу частину встановленого інтерфейсу.
Антті Хаапала

3
Видалили ... але чому? Оскільки це робить порт python 2 для python 3 ще одну роботу.
Фрукти

1
@ 林果 皞: Вся суть нової основної версії полягає в тому, що розробники можуть ввести вдосконалення, які можуть включати в себе порушення змін, а не підтримку старих функцій у міру дорослішання мови. Це завжди ризик, який слід враховувати перед оновленням до нової основної версії. У цьому випадку inвін коротший і більш пітонічний, а також узгоджується з іншими колекціями на мові.
johnnyRose

23

has_key застаріла в Python 3.0 . Ви також можете використовувати 'in'

graph={'A':['B','C'],
   'B':['C','D']}

print('A' in graph)
>> True

print('E' in graph)
>> False

17

У python3 has_key(key)замінено на__contains__(key)

Перевірено в python3.7:

a = {'a':1, 'b':2, 'c':3}
print(a.__contains__('a'))

5

Я думаю, що вважається "більш пітонічним" просто використовувати inпри визначенні того, чи ключ уже існує, як у

if start not in graph:
    return None

Я не впевнений, згідно з «Zen of Python» (PEP 20): «Явне краще, ніж неявне». Я думаю, що якщо ви використовуєте inключове слово, ваш намір може бути недостатньо чітким, що if start not in graph:означає? може бути graph, це список, і він перевіряє, чи немає такого рядка у списку? З іншого боку, якщо ви використовуєте синтаксис типу has_key(зараз застарілий) або, принаймні in graph.keys(), більш зрозуміло, що graphцеdict
Amitay Drummer

4

Весь код у документі буде:

graph = {'A': ['B', 'C'],
             'B': ['C', 'D'],
             'C': ['D'],
             'D': ['C'],
             'E': ['F'],
             'F': ['C']}
def find_path(graph, start, end, path=[]):
        path = path + [start]
        if start == end:
            return path
        if start not in graph:
            return None
        for node in graph[start]:
            if node not in path:
                newpath = find_path(graph, node, end, path)
                if newpath: return newpath
        return None

Після написання збережіть документ і натисніть F 5

Після цього код, який ви будете запускати в оболонці Python IDLE, буде таким:

find_path (графік, 'A', 'D')

Відповідь, яку ви повинні отримати в IDLE, - це

['A', 'B', 'C', 'D'] 

Ви можете пояснити це? Конкретно рекурсійну частину.
розшифровка

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.