L'objet 'dict' n'a pas d'attribut 'has_key'


105

En parcourant un graphique en Python, je reçois cette erreur:

L'objet 'dict' n'a pas d'attribut 'has_key'

Voici mon code:

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

Le code vise à trouver les chemins d'un nœud à d'autres. Source du code: http://cs.mwsu.edu/~terry/courses/4883/lectures/graphs.html

Pourquoi est-ce que j'obtiens cette erreur et comment puis-je la corriger?


2
if not start in graph:
Peter Wood

1
Possible duplication de 'has_key ()' ou 'in'?
Peter Wood

Réponses:


180

has_keya été supprimé dans Python 3. De la documentation :

  • Supprimé dict.has_key()- utilisez inplutôt l' opérateur.

Voici un exemple:

if start not in graph:
    return None

1
Je pense que key not in d.keys()c'est probablement beaucoup plus lent aussi, car key not in ddevrait être une recherche O (1) et je crois qu'elle keysproduit une liste, qui est une recherche O (n) (sans parler de la prise d'espace supplémentaire en mémoire). Je pourrais me tromper à ce sujet - il pourrait encore s'agir d'une recherche hachée
Adam Smith

3
@AdamSmith pas dans Python 3, d.keys()est une vue qui implémente la plupart de l'interface définie.
Antti Haapala

3
Il a été supprimé ... mais pourquoi? Puisqu'il rend le portage de python 2 vers python 3 plus de travail à faire.
Fruit

1
@ 林果 皞: L'intérêt d'une nouvelle version majeure est que les développeurs peuvent introduire des améliorations qui peuvent inclure des changements de rupture au lieu d'avoir à supporter d'anciennes fonctionnalités à mesure que le langage évolue. Il s'agit toujours d'un risque qui doit être pris en compte avant de passer à une nouvelle version majeure. Dans ce cas, inest plus court et plus pythonique, tout en étant cohérent avec d'autres collections de la langue.
johnnyRose

23

has_key est obsolète dans Python 3.0 . Vous pouvez également utiliser «in»

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

print('A' in graph)
>> True

print('E' in graph)
>> False

17

En python3, has_key(key)est remplacé par__contains__(key)

Testé en python3.7:

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

5

Je pense qu'il est considéré comme "plus pythonique" de l'utiliser uniquement inpour déterminer si une clé existe déjà, comme dans

if start not in graph:
    return None

Je ne suis pas sûr, selon The Zen of Python (PEP 20): "Explicite vaut mieux qu'implicite". Je pense que si vous utilisez le inmot - clé, votre intention n'est peut-être pas assez claire. Qu'est-ce que cela if start not in graph:signifie? peut être graphest une liste et il vérifie s'il n'y a pas une telle chaîne dans la liste? D'autre part, si vous utilisez une syntaxe comme has_key(maintenant obsolète) ou du moins, in graph.keys()il est plus clair que graphc'estdict
Amitay Drummer

4

L'ensemble du code du document sera:

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

Après l'avoir écrit, enregistrez le document et appuyez sur F 5

Après cela, le code que vous exécuterez dans le shell Python IDLE sera:

find_path (graphique, 'A', 'D')

La réponse que vous devriez recevoir dans IDLE est

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

Pouvez-vous l'expliquer, en particulier la partie récursivité.
Chiffrer

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.