317 votes

Sont imbriqués les blocs try/except en python une bonne programmation de la pratique?

Je suis en train d'écrire mon propre conteneur, qui doit donner accès à un dictionnaire à l'intérieur par l'attribut appels. L'utilisation typique du conteneur serait comme ceci:

temp_container = DictContainer()
dict_container['foo'] = bar
...
print dict_container.foo

Je sais que cela pourrait être stupide pour écrire quelque chose comme cela, mais c'est la fonctionnalité j'ai besoin de fournir. Je pensais à la mise en œuvre de ce de façon suivante:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        try:
            return self.dict[item]
        except KeyError:
            print "The object doesn't have such attribute"

Je ne suis pas sûr de savoir si imbriqués les blocs try/except sont une bonne pratique, et donc une autre façon serait d'utiliser hasattr() et has_key():

def __getattribute__(self, item):
        if hasattr(self, item):
            return object.__getattribute__(item)
        else:
            if self.dict.has_key(item):
                return self.dict[item]
            else:
                raise AttributeError("some customised error")

Ou d'utiliser l'un d'eux et essayer un bloc catch comme ceci:

def __getattribute__(self, item):
    if hasattr(self, item):
        return object.__getattribute__(item)
    else:
        try:
            return self.dict[item]
        except KeyError:
            raise AttributeError("some customised error")

L'option la plus pythonic et élégant?

280voto

lqc Points 2498

Votre premier exemple est parfaitement bien. Même l'officiel de Python docs recommande ce style connu comme l'aeap.

Personnellement, je préfère éviter de nidification quand il n'est pas nécessaire:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass  # fallback to dict
    try:
        return self.dict[item]
    except KeyError:
        raise AttributeError("The object doesn't have such attribute") from None

PS. has_key() a été supprimée pour une longue période en Python 2. Utiliser item in self.dict à la place.

27voto

Bruno Polaco Points 803

Alors qu'en Java de ses, en effet, une mauvaise pratique d'utiliser les Exceptions pour le contrôle de flux (principalement parce que les exceptions de la force de la jvm pour rassembler des ressources (plus ici)), en Python, vous avez 2 principes importants: Duck-Typing et de l'aeap. Cela signifie essentiellement que vous êtes encouragé à essayer à l'aide d'un objet de la manière que vous pensez qu'il serait de travailler et de traiter quand les choses ne sont pas comme ça.

En résumé, le seul problème serait votre code d'arriver trop en retrait. Si vous en avez envie, essayez de simplifier certaines des imbrications comme lqc suggéré

16voto

BrenBarn Points 63718

Pour votre exemple, vous n'avez pas réellement besoin de les imbriquer. Si l'expression dans l' try bloc réussit, la fonction sera de retour, de sorte que tout code, après tout le try/except bloc n'est exécutée que si la première tentative échoue. Ainsi, vous pouvez simplement faire:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass
    # execution only reaches here when try block raised AttributeError
    try:
        return self.dict[item]
    except KeyError:
        print "The object doesn't have such attribute"

La nidification n'est pas mauvais, mais j'ai envie de la laisser à plat rend la structure plus claire: vous êtes à la façon séquentielle d'essayer une série de choses et le retour de la première qui fonctionne.

D'ailleurs, vous voudrez peut-être penser si vous voulez vraiment utiliser __getattribute__ au lieu de __getattr__ ici. À l'aide de __getattr__ permettra de simplifier les choses, car vous saurez que la normal attribut processus de recherche a déjà échoué.

8voto

martineau Points 21665

À mon avis, ce serait le plus Pythonic façon de le gérer, même si et parce qu'il est de votre question discutable. Notez que ceci définit__getattr__()au lieu de__getattribute__() , car cela signifie qu'il n'a qu'à composer avec le "spécial" d'attributs garder dans le dictionnaire interne.

def __getattr__(self, name):
    """only called when an attribute lookup in the usual places has failed"""
    try:
        return self.my_dict[name]
    except KeyError:
        raise AttributeError("some customized error message")

5voto

En Python il est plus facile de demander pardon que demander la permission. Ne vous inquiétez pas imbriquée à l'exception de la manipulation.

(En plus, en has* utilise presque toujours des exceptions en vertu de la couverture de toute façon.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X