166 votes

Comment retourner une valeur de __init__ en Python ?

J'ai une classe avec un __init__ fonction.

Comment puis-je retourner une valeur entière à partir de cette fonction lorsqu'un objet est créé ?

J'ai écrit un programme, où __init__ fait l'analyse syntaxique de la ligne de commande et j'ai besoin qu'une valeur soit définie. Est-il possible de la définir dans une variable globale et de l'utiliser dans d'autres fonctions membres ? Si oui, comment faire ? Jusqu'à présent, j'ai déclaré une variable en dehors de la classe et le fait de la définir dans une fonction ne se reflète pas dans les autres fonctions.

9 votes

Si vous envisagiez de renvoyer un code d'erreur, levez une exception à la place.

1 votes

Veuillez supprimer votre commentaire et mettre à jour votre question. La question vous appartient. C'est votre question. Veuillez corriger la question pour montrer correctement quel est votre véritable problème. Vous utilisez mal __init__ nous pouvons vous aider si vous décrivez ce que vous essayez vraiment d'accomplir.

2 votes

__init__ devrait probablement no faire l'analyse de la ligne de commande. Définissez une méthode de classe qui effectue l'analyse syntaxique réelle, et passez les valeurs analysées à la classe __init__ . Soit __init__ se préoccuper de la création des attributs nécessaires, et non de la manière de produire les valeurs de ces attributs.

212voto

Jacek Konieczny Points 4002

Pourquoi voulez-vous faire ça ?

Si vous souhaitez renvoyer un autre objet lorsqu'une classe est appelée, utilisez la fonction __new__() método:

class MyClass(object):
    def __init__(self):
        print "never called in this case"
    def __new__(cls):
        return 42

obj = MyClass()
print obj

15 votes

Oui, nouveau est la bonne façon de retourner autre chose qu'une instance de classe lorsqu'on utilise une classe... Je me demande simplement - y a-t-il une raison pour laquelle vous voudriez vraiment FAIRE cela ?

51 votes

@weronika Une idée : dans toute situation où vous utiliseriez normalement une factory, mais où vous avez une raison de vouloir présenter une interface qui ressemble à une instanciation de classe normale. Exemple : lorsque vous ajoutez de nouveaux paramètres optionnels dans la classe __init__ Vous vous rendez compte que, pour obtenir la flexibilité souhaitée, vous avez besoin d'une fabrique de classes qui renvoie des instances de sous-classes spécialisées. Mais les utilisateurs de votre bibliothèque utilisent déjà votre API existante. Pour la préserver, vous surchargez __new__ pour renvoyer les instances de vos sous-classes spécialisées.

18 votes

Si vous voulez voir un exemple de ce que Mark Amery a dit, consultez le code source de l'application datetime de la bibliothèque standard. Il utilise __new__ exactement de cette façon.

172voto

Can Berk Güder Points 39887

__init__ doit retourner None. Vous ne pouvez pas (ou du moins ne devriez pas) renvoyer quelque chose d'autre.

Essayez de faire en sorte que ce que vous voulez retourner soit une variable d'instance (ou une fonction).

>>> class Foo:
...     def __init__(self):
...         return 42
... 
>>> foo = Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None

38 votes

+1 : Vous ne peut pas retourner quelque chose d'autre. Ça n'a aucun sens.

84 votes

init ne renvoie pas l'objet nouvellement créé - comme on le voit dans l'erreur de type, il est nécessaire de renvoyer None, n'est-ce pas ? L'objet nouvellement créé est retourné par nouveau , init ne fait que définir certains de ses attributs. Mais oui, comme vous l'avez dit, changer init o nouveau pour renvoyer quelque chose d'autre n'a vraiment aucun sens.

0 votes

Où se trouve new ici ? Est-ce que new implicite en Python ? Je supposais que la sémantique de Python était différente de celle de Java et des autres langages qui utilisent ce mot.

45voto

nosklo Points 75862

Desde el la documentation de __init__ :

En tant que contrainte spéciale sur les constructeurs, aucune valeur ne peut être renvoyée ; si c'est le cas, une TypeError sera levée au moment de l'exécution.

Pour preuve, ce code :

class Foo(object):
    def __init__(self):
        return 2

f = Foo()

Donne cette erreur :

Traceback (most recent call last):
  File "test_init.py", line 5, in <module>
    f = Foo()
TypeError: __init__() should return None, not 'int'

24voto

PMN Points 81

Un exemple d'utilisation de la matière en question peut être comme :

class SampleObject(object):

    def __new__(cls, item):
        if cls.IsValid(item):
            return super(SampleObject, cls).__new__(cls)
        else:
            return None

    def __init__(self, item):
        self.InitData(item) #large amount of data and very complex calculations

...

ValidObjects = []
for i in data:
    item = SampleObject(i)
    if item:             # in case the i data is valid for the sample object
        ValidObjects.append(item)

_Je n'ai pas assez de réputation donc je ne peux pas écrire de commentaire, c'est fou ! J'aimerais pouvoir le poster en commentaire à weronika_

3 votes

Cela provoquera une NameError : self n'est pas défini dans __new__(cls, Item)

11voto

gruszczy Points 14097

__init__ ne retourne rien et devrait toujours retourner None .

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