Obiekt „dict” nie ma atrybutu „has_key”


105

Podczas przeglądania wykresu w Pythonie otrzymuję następujący błąd:

Obiekt „dict” nie ma atrybutu „has_key”

Oto mój kod:

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

Kod ma na celu znalezienie ścieżek z jednego węzła do drugiego. Źródło kodu: http://cs.mwsu.edu/~terry/courses/4883/lectures/graphs.html

Dlaczego otrzymuję ten błąd i jak mogę go naprawić?


2
if not start in graph:
Peter Wood

Odpowiedzi:


180

has_keyzostał usunięty w Pythonie 3. Z dokumentacji :

  • Usunięto dict.has_key()- inzamiast tego użyj operatora.

Oto przykład:

if start not in graph:
    return None

1
Myślę, że key not in d.keys()jest to prawdopodobnie znacznie wolniejsze, ponieważ key not in dpowinno być wyszukiwaniem O (1) i uważam, że keystworzy listę, która jest wyszukiwaniem O (n) (nie wspominając o zajęciu dodatkowego miejsca w pamięci). Mogę się jednak co do tego mylić - nadal może to być hashowane wyszukiwanie
Adam Smith

3
@AdamSmith nie w Pythonie 3, d.keys()to widok, który implementuje większość ustawionego interfejsu.
Antti Haapala

3
Usunięto ... ale dlaczego? Ponieważ sprawia, że ​​port Pythona 2 do Pythona 3 wymaga więcej pracy.
Owoce

1
@ 林果 皞: Celem nowej wersji głównej jest to, że programiści mogą wprowadzać ulepszenia, które mogą obejmować istotne zmiany zamiast obsługiwać stare funkcje w miarę dojrzewania języka. Jest to zawsze ryzyko, które należy wziąć pod uwagę przed aktualizacją do nowej wersji głównej. W tym przypadku injest krótszy i bardziej Pythonic, a także jest spójny z innymi zbiorami w tym języku.
johnnyRose

23

has_key stał się przestarzały w Pythonie 3.0 . Alternatywnie możesz użyć „w”

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

print('A' in graph)
>> True

print('E' in graph)
>> False

17

W python3 has_key(key)jest zastępowany przez__contains__(key)

Testowane w pythonie 3.7:

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

5

Myślę, że jest uważane za „bardziej pythonowe”, ingdy używa się go tylko przy określaniu, czy klucz już istnieje, jak w

if start not in graph:
    return None

Nie jestem pewien, zgodnie z The Zen of Python (PEP 20): „Wyraźne jest lepsze niż ukryte”. Myślę, że jeśli użyjesz insłowa kluczowego, twój zamiar może nie być wystarczająco jasny, co to if start not in graph:znaczy? może być graphlistą i sprawdza, czy nie ma takiego ciągu na liście? Z drugiej strony, jeśli używasz składni takiej jak has_key(obecnie przestarzała) lub przynajmniej in graph.keys()jest to bardziej jasne, że graphjest todict
Amitay Drummer

4

Cały kod w dokumencie będzie wyglądał następująco:

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

Po napisaniu zapisz dokument i naciśnij F 5

Następnie kod, który uruchomisz w powłoce Python IDLE będzie wyglądał następująco:

find_path (wykres, „A”, „D”)

Odpowiedź, którą powinieneś otrzymać w IDLE, brzmi

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

Czy możesz to wyjaśnić, a konkretnie część rekursji.
Encipher

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.