Apprendre Python , et a quelques doutes fondamentaux.
1.J'ai vu la déclaration de variable (chemin ici) comme
class writer:
path = ""
parfois, pas de déclaration explicite mais initialiser via __init__
.
def __init__(self, name):
self.name = name
Je comprends le but de __init__
, mais est-il conseillé de déclarer une variable dans toute autre fonction.
2. Comment puis-je créer une variable pour contenir un type personnalisé?
class writer:
path = "" # string value
customObj = ??
__name__
attribut ont un "nom". Tous les objets n'ont pas d'__name__
attribut, mais vous pouvez toujours y faire référence. Si nous commençons à appeler une «référence» un «nom», nous rendons un mauvais service aux débutants sur la piste.Réponses:
D'accord, tout d'abord.
Il n'y a pas de "déclaration de variable" ou "d'initialisation de variable" en Python.
Il y a simplement ce que nous appelons «affectation», mais nous devrions probablement simplement appeler «nommer».
L'affectation signifie "ce nom sur le côté gauche se réfère maintenant au résultat de l'évaluation du côté droit, indépendamment de ce à quoi il faisait référence 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 font. Vous pouvez réappliquer le même nom à n'importe quoi quel que soit son type, mais l'objet 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 créez pas de variables pour contenir un type personnalisé. Vous ne créez pas de variables pour contenir un type particulier. Vous ne "créez" pas du tout de variables. 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
bloc fait partie de la classe . Ainsi, les fonctions (def
) écrites ici sont des méthodes, c'est-à-dire une partie de l'objet de classe (non stocké par instance), tout comme en Java, C ++ et C #; mais d'autres noms ici font é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 également des objets en Python. Donc:class Example: data = 42 def method(self): pass
Les classes sont aussi des objets , en Python.
Alors maintenant, nous avons créé un objet nommé
Example
, qui représente la classe de toutes les choses qui sontExample
s. Cet objet a deux attributs fournis par l'utilisateur (en C ++, «membres»; en C #, «champs ou propriétés ou méthodes»; en Java, «champs ou méthodes»). L'un d'eux est nommédata
et stocke la valeur entière42
. L'autre est nommémethod
et stocke un objet fonction. (Il y a plusieurs autres attributs que Python ajoute automatiquement.)Cependant, ces attributs ne font toujours pas vraiment partie de l'objet. Fondamentalement, un objet est juste un ensemble de noms supplémentaires (les noms d'attributs), jusqu'à ce que vous arriviez à 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 configurez délibérément.
Créons une instance:
Nous avons maintenant un objet distinct nommé
x
, qui est une instance deExample
. Lesdata
etmethod
ne font pas réellement partie de l'objet, mais nous pouvons toujours les rechercher via àx
cause de la magie que Python fait dans les coulisses. Lorsque nous recherchonsmethod
, en particulier, nous obtiendrons à la place une "méthode liée" (lorsque nous l'appelons, ellex
est passée automatiquement enself
paramètre, ce qui ne peut pas arriver si nous recherchonsExample.method
directement).Que se passe-t-il lorsque nous essayons d'utiliser
x.data
?Lorsque nous l'examinons, il est d'abord recherché dans l'objet. S'il ne se trouve pas dans l'objet, Python regarde dans la classe.
Cependant, lorsque nous attribuons à
x.data
, Python créera un attribut sur l'objet. Il ne remplacera pas l'attribut de la classe.Cela nous permet de faire l' initialisation des objets . Python appellera automatiquement la
__init__
méthode de la classe sur les nouvelles instances lors de leur création, le cas échéant. 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
Maintenant, nous devons spécifier a
name
lorsque nous créons unExample
, et chaque instance a la siennename
. Python ignorera l'attribut de classeExample.name
chaque fois que nous recherchons.name
une instance, car l'attribut de l'instance sera trouvé en premier.Une dernière mise en garde: la modification (mutation) et l'assignation sont des choses différentes!
En Python, les chaînes sont immuables. Ils ne peuvent pas être modifiés. Quand vous faites:
a = 'hi ' b = a a += 'mom'
Vous ne modifiez pas la chaîne «hi» d'origine. C'est impossible en Python. Au lieu de cela, vous créez une nouvelle chaîne
'hi mom'
et faitesa
cesser d'être un nom pour'hi '
, et commencez à être un nom à la'hi mom'
place. Nous avons faitb
un nom pour'hi '
ainsi, et après avoir réappliqué lea
nom, ilb
est toujours un nom pour'hi '
, car'hi '
il existe toujours et n'a pas été changé.Mais les listes peuvent être modifiées:
a = [1, 2, 3] b = a a += [4]
Maintenant,
b
c'est [1, 2, 3, 4] aussi, parce que nous avons faitb
un nom pour la même chose quia
nommait, puis nous avons changé cette chose. Nous n'avons pas créé de nouvelle liste poura
to name, car Python traite simplement+=
différemment les listes.Ceci est important pour les objets car si vous aviez une liste comme attribut de classe et que vous utilisiez une instance pour modifier la liste, alors le changement serait "vu" dans toutes les autres instances. Cela est dû au fait que (a) les données font en fait partie de l'objet de classe, et non d'un objet d'instance; (b) parce que vous modifiiez la liste et ne faisiez pas une simple affectation, vous n'avez pas créé un nouvel attribut d'instance masquant l'attribut de classe.
la source
Cela peut avoir 6 ans de retard, mais dans Python 3.5 et supérieur, vous déclarez un type de variable comme celui-ci:
ou ca:
variable_name # type: shinyType
Donc, dans votre cas (si vous avez une
CustomObject
classe définie), vous pouvez faire:Voir ceci ou cela pour plus d'informations.
la source
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 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 limiter cela.Votre question concerne spécifiquement les classes, les objets et les variables d'instance. La façon idiomatique de créer des variables d'instance se trouve dans la
__init__
méthode et nulle part ailleurs - alors que vous pouvez créer de nouvelles variables d'instance dans d'autres méthodes, ou même dans du code non lié, c'est juste 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. Désormais, 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 noms de la classe elle-même conduit à un comportement totalement différent. C'est fonctionnellement différent, et vous ne devriez le faire que si vous avez une raison spécifique. Par exemple:
class Thing(object): magic = "Magic" def __init__(self): pass
Essayez maintenant:
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 noms de la classe elle-même est différent de l'espace de noms des objets créés à partir de celle-ci. Je vous laisse le soin de faire des recherches un peu plus.
Le message à retenir est que Python idiomatique doit (a) initialiser les attributs d'objet dans votre
__init__
méthode et (b) documenter le comportement de votre classe si nécessaire. Vous n'avez pas besoin de vous soucier de la documentation complète de niveau Sphinx pour tout ce que vous écrivez, mais au moins quelques commentaires sur les détails que vous ou quelqu'un d'autre pourriez avoir besoin pour le récupérer.la source
À des fins de cadrage, j'utilise:
custom_object = None
la source
Les variables ont une portée, donc oui, il est approprié d'avoir des variables spécifiques à votre fonction. Vous n'avez pas toujours besoin d'être explicite sur leur définition; généralement, vous pouvez simplement les utiliser. Seulement si vous voulez faire quelque chose de spécifique au type de la variable, comme ajouter pour une liste, vous devez les définir avant de commencer à les utiliser. Exemple typique de ceci.
list = [] for i in stuff: list.append(i)
En passant, ce n'est pas vraiment un bon moyen de configurer la liste. Il vaudrait mieux dire:
list = [i for i in stuff] # list comprehension
... mais je m'éloigne du sujet.
Votre autre question. L'objet personnalisé doit être une classe elle-même.
class CustomObject(): # always capitalize the class name...this is not syntax, just style. pass customObj = CustomObject()
la source