Que font __init__ et self sur Python?


796

J'apprends le langage de programmation Python et je suis tombé sur quelque chose que je ne comprends pas complètement.

Dans une méthode comme:

def method(self, blah):
    def __init__(?):
        ....
    ....

Que fait self-il? Qu'est-ce que c'est? Est-ce obligatoire?

Que fait la __init__méthode? Pourquoi est-ce nécessaire? (etc.)

Je pense que ce peuvent être des constructions OOP, mais je ne sais pas grand-chose.

Réponses:


585

Dans ce code:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... la selfvariable représente l'instance de l'objet lui-même. La plupart des langages orientés objet transmettent cela comme un paramètre caché aux méthodes définies sur un objet; Python ne fonctionne pas. Vous devez le déclarer explicitement. Lorsque vous créez une instance de la Aclasse et appelez ses méthodes, elle sera transmise automatiquement, comme dans ...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

La __init__méthode est à peu près ce qui représente un constructeur en Python. Lorsque vous appelez A()Python, crée un objet pour vous et le transmet en tant que premier paramètre à la __init__méthode. Tous les paramètres supplémentaires (par exemple, A(24, 'Hello')) seront également passés en tant qu'arguments - dans ce cas, provoquant une exception, car le constructeur ne les attend pas.


8
que faire si vous mettez x = 'Hello'dehors init mais à l'intérieur de la classe? est-ce comme java où c'est pareil, ou devient-il comme une variable statique qui n'est initialisée qu'une seule fois?
Jayen

15
C'est comme une variable statique. Il n'est initialisé qu'une seule fois et est disponible via A.xou a.x. Notez que le remplacer sur une classe spécifique n'affectera pas la base, donc A.x = 'foo'; a.x = 'bar'; print a.x; print A.ximprimera baralorsfoo
Chris B.

156
Il convient de souligner que le premier argument ne doit pas nécessairement être appelé self, c'est simplement par convention.
Henry Gomersall

13
À quoi sert la objectdéclaration de classe? J'ai remarqué que certaines classes en ont et d'autres non
Chris

9
@Chris C'est pour la compatibilité avec Python 2. En Python 3, il n'est pas nécessaire d'hériter explicitement objectcar cela se produit par défaut.
Gabriel

241

Oui, vous avez raison, ce sont des constructions oop.

__init__est le constructeur d'une classe. Le selfparamètre fait référence à l'instance de l'objet (comme thisen C ++).

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

La __init__méthode est appelée lorsque la mémoire de l'objet est allouée:

x = Point(1,2)

Il est important d'utiliser le selfparamètre à l'intérieur de la méthode d'un objet si vous souhaitez conserver la valeur avec l'objet. Si, par exemple, vous implémentez la __init__méthode comme ceci:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

Vos paramètres xet yseraient stockés dans des variables sur la pile et seraient ignorés lorsque la méthode init sortira du cadre. Définir ces variables en tant que self._xet self._ydéfinit ces variables en tant que membres de l' Pointobjet (accessible pendant la durée de vie de l'objet).


1
Alors, y a-t-il une raison pour laquelle vous ne voudriez selfpas être dans le constructeur? Pourquoi devez-vous même le préciser, ne serait-il pas préférable que ce soit implicite?
Aaron Franke

Pour autant que je sache, __ init __ n'est pas un constructeur, c'est la première méthode qui sera exécutée lorsqu'un objet est créé, __ init __ est utilisé pour configurer l'objet. __ new __ est le constructeur en python.
Deepanshu

207

Un bref exemple illustratif

Dans l'espoir que cela puisse aider un peu, voici un exemple simple que j'ai utilisé pour comprendre la différence entre une variable déclarée à l'intérieur d'une classe et une variable déclarée à l'intérieur d'une __init__fonction:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

Production:

345
123

7
Observation intéressante mais je pense que vous êtes sur la mauvaise voie. Avec print MyClass.i, on dirait plus que vous appelez un variablie 'statique' i. Où, comme avec ai, vous appelez une variable membre, i. Il me semble qu'init n'est qu'un constructeur qui est d'abord exécuté lorsque vous créez un objet de la classe.
captainspi

34
C'est ce que j'essayais de «m'expliquer» avec cet exemple - que la variable définie par __init__est ce qui est transmis aux instances de la classe, pas la variable «statique» de la classe elle-même qui porte le même nom ...
Dave Everitt

44

En bref:

  1. selfcomme il le suggère, se réfère à lui - même - l'objet qui a appelé la méthode. Autrement dit, si vous avez N objets appelant la méthode, alors self.afera référence à une instance distincte de la variable pour chacun des N objets. Imaginez N copies de la variable apour chaque objet
  2. __init__est ce qu'on appelle en tant que constructeur dans d'autres langages OOP tels que C ++ / Java. L'idée de base est qu'il s'agit d'une méthode spéciale qui est automatiquement appelée lorsqu'un objet de cette classe est créé

29

__init__agit comme un constructeur. Vous devrez passer "self" à toutes les fonctions de classe comme premier argument si vous voulez qu'elles se comportent comme des méthodes non statiques. "self" sont des variables d'instance pour votre classe.


1
'self' définit si une méthode est statique ou non! Wow, c'est une révélation pour ce gars de Java.
liwevire

25

Essayez ce code. J'espère que cela aide de nombreux programmeurs C comme moi à apprendre Py.

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

Production:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay


Je ne sais pas si c'est juste moi, mais lire ce code était un peu déroutant. C'est peut-être parce que je suis toujours un programmeur novice en Python, idk.
Linny

Je ne suis pas clair sur la chose doc .. cela tire-t-il la documentation? et si je fais: '' 'test - mon doc' '', puis-je utiliser: print.p .__ test__? ou doc ​​est-il un mot-clé spécifique?
Thomas

@Thomas doc est le mot-clé pour les détails documentés. Les guillemets triples sont utilisés pour noter les documents et le document est une entité facultative.
Jayzcode

25

Les objets de classe prennent en charge deux types d'opérations: les références d'attribut et l'instanciation

Les références d'attribut utilisent la syntaxe standard utilisée pour toutes les références d'attribut dans Python: obj.name. Les noms d'attribut valides sont tous les noms qui se trouvaient dans l'espace de noms de la classe lorsque l'objet de classe a été créé. Donc, si la définition de classe ressemblait à ceci:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

alors MyClass.iet MyClass.fsont des références d'attribut valides, renvoyant respectivement un entier et un objet fonction. Les attributs de classe peuvent également être affectés à, vous pouvez donc modifier la valeur de MyClass.ipar affectation. __doc__est également un attribut valide, renvoyant la docstring appartenant à la classe: "Un exemple de classe simple".

L'instanciation de classe utilise la notation de fonction. Imaginez simplement que l'objet classe est une fonction sans paramètre qui renvoie une nouvelle instance de la classe. Par exemple:

x = MyClass()

L' opération d' instanciation («appeler» un objet de classe) crée un objet vide. De nombreuses classes aiment créer des objets avec des instances personnalisées à un état initial spécifique. Par conséquent, une classe peut définir une méthode spéciale nommée __init__(), comme ceci:

def __init__(self):
    self.data = []

Lorsqu'une classe définit une __init__()méthode, l'instanciation de classe appelle automatiquement __init__()pour l'instance de classe nouvellement créée. Ainsi, dans cet exemple, une nouvelle instance initialisée peut être obtenue par:

x = MyClass()

Bien sûr, la __init__()méthode peut avoir des arguments pour une plus grande flexibilité. Dans ce cas, les arguments donnés à l'opérateur d'instanciation de classe sont transmis à __init__(). Par exemple,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

Tiré de la documentation officielle qui m'a le plus aidé au final.


Voici mon exemple

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

Lorsque vous créez une instance de classe Bill:

purchase = Bill(5,6,7)

Vous obtenez:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)

22

J'ai eu du mal à comprendre cela moi-même. Même après avoir lu les réponses ici.

Pour bien comprendre la __init__méthode, vous devez vous comprendre.

Le paramètre auto

Les arguments acceptés par la __init__méthode sont:

def __init__(self, arg1, arg2):

Mais nous ne lui transmettons en fait que deux arguments:

instance = OurClass('arg1', 'arg2')

D'où vient l'argument supplémentaire?

Lorsque nous accédons aux attributs d'un objet, nous le faisons par nom (ou par référence). Ici, l'instance est une référence à notre nouvel objet. Nous accédons à la méthode printargs de l'objet instance à l'aide de instance.printargs.

Afin d'accéder aux attributs d'objet à partir de la __init__méthode, nous avons besoin d'une référence à l'objet.

Chaque fois qu'une méthode est appelée, une référence à l'objet principal est transmise comme premier argument. Par convention, vous appelez toujours ce premier argument à vos méthodes.

Cela signifie que dans la __init__méthode que nous pouvons faire:

self.arg1 = arg1
self.arg2 = arg2

Ici, nous définissons des attributs sur l'objet. Vous pouvez le vérifier en procédant comme suit:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

des valeurs comme celle-ci sont appelées attributs d'objet. Ici, la __init__méthode définit les attributs arg1 et arg2 de l'instance.

source: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method


17

notez que cela selfpourrait en fait être n'importe quel identifiant python valide. Par exemple, nous pourrions tout aussi facilement écrire, à partir de l'exemple de Chris B:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

et cela fonctionnerait exactement de la même manière. Il est cependant recommandé d'utiliser self car les autres pythoners le reconnaîtront plus facilement.


Je suis d'accord que l'auto serait recommandé à la place de foo, aide d'autres programmeurs à regarder le code
Linny

15

Fondamentalement, vous devez utiliser le mot-clé «self» lorsque vous utilisez une variable dans plusieurs fonctions au sein de la même classe. Quant à init , il est utilisé pour configurer les valeurs par défaut car aucune autre fonction de cette classe n'est appelée.


6
Il n'y a pas de mot-clé 'self' en Python. L'appel du premier paramètre «self» est simplement une convention.
David Anderson

self est essentiellement utilisé comme espace réservé. Il n'est pas nécessaire que vous vous utilisiez vous-même, vous pouvez utiliser "eeee" ou "foo" ou autre chose, il est juste recommandé pour les autres programmeurs lors de la lecture de votre code
Linny

15
  1. __init__est fondamentalement une fonction qui "initialisera" / "activera" les propriétés de la classe pour un objet spécifique, une fois créée et mise en correspondance avec la classe correspondante.
  2. self représente cet objet qui héritera de ces propriétés.

1
le mot-clé "self" ne doit pas être utilisé, c'est juste un espace réservé. Vous pouvez utiliser n'importe quel mot, mais il est recommandé d'utiliser self pour améliorer la lisibilité du programme
Linny

13

Le 'self' est une référence à l'instance de classe

class foo:
    def bar(self):
            print "hi"

Maintenant, nous pouvons créer une instance de foo et appeler la méthode dessus, le paramètre self est ajouté par Python dans ce cas:

f = foo()
f.bar()

Mais il peut aussi être passé si l'appel de méthode n'est pas dans le contexte d'une instance de la classe, le code ci-dessous fait la même chose

f = foo()
foo.bar(f)

Fait intéressant, le nom de variable «self» n'est qu'une convention. La définition ci-dessous fonctionnera exactement de la même manière. Cela dit, il s'agit d' une convention très forte qui doit toujours être suivie , mais elle dit quelque chose sur la nature flexible du langage.

class foo:
    def bar(s):
            print "hi"

Pourquoi cela dit-il quelque chose sur la nature flexible de la langue? Il dit simplement que vous pouvez donner aux variables le nom légal que vous choisissez. En quoi est-ce différent de tout autre langage de programmation?
Daniel

Comme je l'ai écrit dans ma réponse, "bar" n'est qu'une fonction dans laquelle une instance de classe est fournie comme premier paramètre. Ainsi, alors que "bar" est défini comme une méthode liée à "foo", elle peut également être appelée avec une instance d'une autre classe. Ce n'est pas ainsi que les méthodes et "ceci" fonctionnent en Java par exemple, bien que j'imagine que vous voyez que ce sont le même concept, les mêmes fonctions et un certain contexte d'instance (le contexte d'instance étant le premier paramètre en Python et "ceci" en Java ") Peut-être pouvez-vous maintenant voir la flexibilité du langage auquel je faisais référence?
tarn

Oui, cela montre la flexibilité de la langue. La façon dont vous avez formulé votre réponse, il semblait que vous disiez que le fait que vous puissiez appeler la variable "self" autre chose (comme s) montrait la flexibilité de python.
Daniel

12

Juste une démo pour la question.

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class

11

Dans ce code:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

Ici, il __init__agit comme un constructeur pour la classe et lorsqu'un objet est instancié, cette fonction est appelée. selfreprésente l'objet instanciant.

c = Cat('Kitty')
c.info()

Le résultat des déclarations ci-dessus sera le suivant:

I am a cat and I am called Kitty

11

Que fait le moi ? Qu'est-ce que c'est ? Est-ce obligatoire ?

Le premier argument de chaque méthode de classe, y compris init, est toujours une référence à l'instance actuelle de la classe . Par convention, cet argument est toujours nommé self. Dans la méthode init,self fait référence à l'objet nouvellement créé; dans d'autres méthodes de classe, il fait référence à l'instance dont la méthode a été appelée.

Python ne vous oblige pas à utiliser " self ". Vous pouvez lui donner le nom que vous voulez. Mais rappelez - vous que le premier argument d'une définition de méthode est une référence à l'objet . Python ajoute l' selfargument à la liste pour vous; vous n'avez pas besoin de l'inclure lorsque vous appelez les méthodes. si vous n'avez pas fourni la méthode self in init, vous obtiendrez une erreur

TypeError: __init___() takes no arguments (1 given)

Que fait la méthode init ? Pourquoi est-ce nécessaire? (etc.)

initest l'abréviation de l'initialisation. C'est un constructeur qui est appelé lorsque vous créez une instance de la classe et ce n'est pas nécessaire . Mais généralement, il est de notre pratique d'écrire la méthode init pour définir l'état par défaut de l'objet. Si vous n'êtes pas prêt à définir un état de l'objet au départ, vous n'avez pas besoin d'écrire cette méthode.


8
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()

5

Python __init__et selfque font-ils?

Qu'est-ce que self -il? Qu'est-ce que c'est? Est-ce obligatoire?

Que fait la __init__méthode? Pourquoi est-ce nécessaire? (etc.)

L'exemple donné n'est pas correct, alors laissez-moi créer un exemple correct basé sur lui:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

Lorsque nous créons une instance de l'objet, le __init__est appelé pour personnaliser l'objet après sa création. Autrement dit, lorsque l' on appelle SomeObjectavec 'blah'ci - dessous (qui pourrait être quelque chose), il est transmis à la __init__fonction de l'argument, blah:

an_object = SomeObject('blah')

L' selfargument est l'instance SomeObjectqui sera affectée àan_object .

Plus tard, nous pourrions vouloir appeler une méthode sur cet objet:

an_object.method()

Faire la recherche en pointillés, c'est-à-dire an_object.method , lie l'instance à une instance de la fonction, et la méthode (comme appelée ci-dessus) est maintenant une méthode "liée" - ce qui signifie que nous n'avons pas besoin de transmettre explicitement l'instance à l'appel de méthode .

L'appel de méthode obtient l'instance car elle était liée à la recherche en pointillé, et lorsqu'elle est appelée, elle exécute le code qu'elle a été programmée pour exécuter.

L' selfargument implicitement passé est appelé selfpar convention. Nous pourrions utiliser tout autre nom Python légal, mais vous serez probablement goudronné et plumé par d'autres programmeurs Python si vous le changez pour autre chose.

__init__est une méthode spéciale, documentée dans la documentation du modèle de données Python . Il est appelé immédiatement après la création de l'instance (généralement via __new__- bien que cela __new__ne soit pas obligatoire sauf si vous sous-classez un type de données immuable).


3

Ici, le gars a écrit assez bien et simplement: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Lisez le lien ci-dessus comme référence à ceci:

self? Alors, quel est ce paramètre auto à toutes les méthodes du client? Qu'Est-ce que c'est? Eh bien, c'est l'instance, bien sûr! Autrement dit, une méthode comme retirer définit les instructions pour retirer de l'argent du compte d'un client abstrait. L'appel de jeff.withdraw (100.0) met ces instructions à utiliser sur l'instance de jeff.

Donc, quand nous disons def retrait (auto, montant):, nous disons, "voici comment vous retirez de l'argent d'un objet Client (que nous appellerons auto) et un chiffre en dollars (que nous appellerons montant). est l'instance du Client qui demande le retrait. Ce n'est pas moi qui fais des analogies non plus. code.

init self peut avoir du sens pour d'autres méthodes, mais qu'en est-il d' init ? Quand on appelle init , nous sommes en train de créer un objet, alors comment peut-il déjà y avoir un soi? Python nous permet d'étendre le self pattern lorsque les objets sont également construits, même s'il ne correspond pas exactement. Imaginez simplement que jeff = Customer ('Jeff Knupp', 1000.0) est le même que d'appeler jeff = Customer (jeff, 'Jeff Knupp', 1000.0); le jeff qui est passé est également le résultat.

C'est pourquoi lorsque nous appelons init , nous initialisons des objets en disant des choses comme self.name = name. Rappelez-vous, puisque self est l'instance, cela revient à dire jeff.name = name, qui est le même que jeff.name = 'Jeff Knupp. De même, self.balance = balance est le même que jeff.balance = 1000.0. Après ces deux lignes, nous considérons l'objet Client "initialisé" et prêt à l'emploi.

Faites attention à ce que vous __init__

Une fois l' init terminé, l'appelant peut à juste titre supposer que l'objet est prêt à être utilisé. Autrement dit, après jeff = Client ('Jeff Knupp', 1000.0), nous pouvons commencer à effectuer un dépôt et à retirer des appels sur jeff; jeff est un objet entièrement initialisé.

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.