114 votes

Déclaration de variables Python

Apprendre Python et a quelques doutes de base.

1. J'ai vu déclaration de variable (chemin ici) comme

class writer:
    path = ""

parfois, pas de déclaration explicite mais initialisation par __init__ .

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

Je comprends l'objectif de __init__ mais est-il conseillé de déclarer une variable dans d'autres fonctions ?

Comment puis-je créer une variable pour contenir un type personnalisé ?

class writer:
    path = "" # string value
    customObj = ??

237voto

Karl Knechtel Points 24349

Ok, chaque chose en son temps.

Il n'existe pas de "déclaration de variable" ou d'"initialisation de variable" en Python.

Il y a simplement ce que nous appelons "affectation", mais que nous devrions probablement appeler simplement "dénomination".

L'assignation signifie "ce nom sur le côté gauche se réfère maintenant au résultat de l'évaluation du côté droit, sans tenir compte de ce à quoi il se référait auparavant (le cas échéant)".

foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

En tant que tels, les noms de Python (un meilleur terme que "variables", sans doute) n'ont pas de types associés ; les valeurs, si. Vous pouvez réappliquer le même nom à n'importe quoi, quel que soit son type, mais la chose a toujours un comportement qui dépend de son type. Le nom est simplement un moyen de faire référence à la valeur (objet). Cela répond à votre deuxième question : Vous Ne le fais pas. créer des variables pour contenir un type personnalisé. Vous ne créez pas de variables pour contenir un type particulier. Vous ne "créez" pas de variables du tout. Vous donnez des noms aux objets.

Deuxième point : Python suit une règle très simple en ce qui concerne les classes, qui est en fait beaucoup plus cohérente que ce que font des langages comme Java, C++ et C# : tout ce qui est déclaré à l'intérieur du class fait partie de la classe . Ainsi, les fonctions ( def ) écrites ici sont des méthodes, c'est-à-dire qu'elles font partie de l'objet de la classe (et ne sont pas stockées par instance), tout comme en Java, C++ et C# ; mais les autres noms ici sont également partie de la classe. Encore une fois, les noms ne sont que des noms, et ils n'ont pas de types associés, et les fonctions sont aussi des objets en Python. Ainsi :

class Example:
    data = 42
    def method(self): pass

Les classes sont aussi des objets en Python.

Nous avons donc créé un objet nommé Example qui représente la classe de toutes les choses qui sont Example s. Cet objet possède deux attributs (En C++, "membres" ; en C#, "champs ou propriétés ou méthodes" ; en Java, "champs ou méthodes"). L'un d'entre eux est nommé data et il stocke la valeur entière 42 . L'autre s'appelle method et il stocke un objet fonction. (Il existe plusieurs autres attributs que Python ajoute automatiquement).

Ces attributs ne font cependant pas vraiment partie de l'objet. Fondamentalement, un objet n'est qu'un paquet de noms supplémentaires (les noms des attributs), jusqu'à ce que l'on arrive à des choses qui ne peuvent plus être divisées. Ainsi, les valeurs peuvent être partagées entre différentes instances d'une classe, ou même entre des objets de différentes classes, si vous le faites délibérément.

Créons une instance :

x = Example()

Maintenant nous avons un objet séparé nommé x qui est une instance de Example . Le site data et method ne font pas réellement partie de l'objet, mais nous pouvons quand même les rechercher via x à cause d'une certaine magie que Python fait dans les coulisses. Lorsque nous cherchons method en particulier, nous obtiendrons plutôt une "méthode liée" (lorsque nous l'appelons, x est transmise automatiquement en tant que self ce qui ne peut pas se produire si l'on recherche Example.method directement).

Que se passe-t-il quand on essaie d'utiliser x.data ?

Quand on l'examine, on le cherche d'abord dans l'objet. S'il n'est pas trouvé dans l'objet, Python le cherche dans la classe.

Cependant, lorsque nous affecter à x.data Python va créer un attribut sur l'objet. Il va pas remplace l'attribut "classe".

Cela nous permet de faire objet initialisation. Python appellera automatiquement la classe __init__ sur les nouvelles instances lorsqu'elles sont créées, si elle est présente. Dans cette méthode, nous pouvons simplement assigner des attributs pour définir les valeurs initiales de cet attribut sur chaque objet :

class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

Nous devons maintenant spécifier un name lorsque nous créons un Example et chaque instance a sa propre name . Python ignorera l'attribut de classe Example.name quand on cherche le .name d'une instance, car l'attribut de l'instance sera trouvé en premier.

Un dernier avertissement : la modification (mutation) et l'affectation sont des choses différentes !

En Python, les chaînes de caractères sont immuables. Elles ne peuvent pas être modifiées. Lorsque vous le faites :

a = 'hi '
b = a
a += 'mom'

Vous ne pas changer la chaîne originale 'hi'. C'est impossible en Python. Au lieu de cela, vous créez un nouveau chaîne de caractères 'hi mom' et causer a pour cesser d'être un nom pour 'hi ' et commencez à être un nom pour 'hi mom' à la place. Nous avons fait b un nom pour 'hi ' également, et après avoir réappliqué le a nom, b est toujours un nom pour 'hi ' parce que 'hi ' existe toujours et n'a pas été modifié.

Mais les listes peuvent être modifiées :

a = [1, 2, 3]
b = a
a += [4]

Maintenant b est [1, 2, 3, 4] aussi, parce que nous avons fait b un nom pour la même chose que a nommé, et ensuite nous avons changé cette chose. Nous n'avons pas créé une nouvelle liste pour a à nommer, car Python traite tout simplement += différemment pour les listes.

Ceci est important pour les objets car si vous avez une liste comme attribut de classe et que vous utilisez une instance pour modifier la liste, le changement sera "vu" dans toutes les autres instances. En effet, (a) les données font en réalité partie de l'objet de classe et non d'un objet d'instance ; (b) comme vous modifiez la liste et que vous ne faites pas une simple affectation, vous n'avez pas créé un nouvel attribut d'instance cachant l'attribut de classe.

40voto

O. Aroesti Points 800

C'est peut-être avec 6 ans de retard, mais dans Python 3.5 et plus, vous déclarez un type de variable comme ceci :

variable_name: type_name

ou ceci :

variable_name # type: shinyType

Donc dans votre cas (si vous avez un CustomObject définie), vous pouvez le faire :

customObj: CustomObject

Voir este ou que pour plus d'informations.

24voto

detly Points 11267

Il n'est pas nécessaire de déclarer de nouvelles variables en Python. Si nous parlons de variables dans des fonctions ou des modules, aucune déclaration n'est nécessaire. Il suffit d'attribuer une valeur à un nom là où vous en avez besoin : mymagic = "Magic" . Les variables en Python peuvent contenir des valeurs de n'importe quel type, et vous ne pouvez pas restreindre cela.

Votre question porte spécifiquement sur les classes, les objets et les variables d'instance. La manière idiomatique de créer des variables d'instance est dans la section __init__ et nulle part ailleurs - alors que vous pourrait créer de nouvelles variables d'instance dans d'autres méthodes, ou même dans du code sans rapport, c'est tout simplement une mauvaise idée. Cela rendra votre code difficile à raisonner ou à maintenir.

Donc, par exemple :

class Thing(object):

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

Facile. Maintenant, les instances de cette classe ont un magic attribut :

thingo = Thing("More magic")
# thingo.magic is now "More magic"

La création de variables dans l'espace de nom de la classe elle-même entraîne un comportement totalement différent. Il est fonctionnellement différent, et vous ne devriez le faire que si vous avez une raison spécifique de le faire. Par exemple :

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

Maintenant, essayez :

thingo = Thing()
Thing.magic = 1
# thingo.magic is now 1

Ou :

class Thing(object):

    magic = ["More", "magic"]

    def __init__(self):
        pass

thing1 = Thing()
thing2 = Thing()
thing1.magic.append("here")
# thing1.magic AND thing2.magic is now ["More", "magic", "here"]

En effet, l'espace de nom de la classe elle-même est différent de l'espace de nom des objets créés à partir de celle-ci. Je vous laisse le soin de faire des recherches plus approfondies à ce sujet.

Le message à retenir est que l'idiome Python consiste à (a) initialiser les attributs de l'objet dans vos __init__ et (b) documenter le comportement de votre classe si nécessaire. Vous n'avez pas besoin d'aller jusqu'à une documentation complète de niveau Sphinx pour tout ce que vous écrivez, mais au moins quelques commentaires sur les détails dont vous ou quelqu'un d'autre pourrait avoir besoin pour le récupérer.

18voto

redhot Points 96

Pour le cadrage, j'utilise :

custom_object = None

1voto

ChipJust Points 864

Les variables ont une portée, donc oui il est approprié d'avoir des variables qui sont spécifiques à votre fonction. Il n'est pas toujours nécessaire d'être explicite quant à leur définition ; en général, vous pouvez simplement les utiliser. Ce n'est que si vous voulez faire quelque chose de spécifique au type de la variable, comme append pour une liste, que vous devez les définir avant de commencer à les utiliser. Exemple typique de ceci.

list = []
for i in stuff:
  list.append(i)

D'ailleurs, ce n'est pas vraiment une bonne façon de configurer la liste. Il serait préférable de dire :

list = [i for i in stuff] # list comprehension

...mais je m'égare.

Votre autre question. L'objet personnalisé devrait être une classe elle-même.

class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()

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