Puisque je suis presque un débutant en python, je vais d'abord regarder la classe (comme une habitude) avec du code simple.
class sampleCls():
pass
Définissez une classe vide. Si vous essayez de sortir les membres de la classe dans cet état,
from pprint import pprint
class sampleCls():
pass
pprint (inspect.getmembers(sampleCls))
Quand tu cours
[('__doc__', None), ('__module__', '__main__')]
Comme ça.
Ajoutez une ligne (au lieu de passer).
class sampleCls():
abc = 111
pprint (inspect.getmembers(sampleCls))
Quand tu cours
[('__doc__', None), ('__module__', '__main__'), ('abc', 111)]
Comme ça.
Après avoir passé la définition de classe, un objet de classe est créé. Les objets de classe peuvent être modifiés. Essayez de modifier l'objet de classe sans créer encore d'instance.
class sampleCls():
abc = 111
#sampleCls.def = 222
sampleCls.efg = 222
pprint (inspect.getmembers(sampleCls))
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
Vous pouvez le changer comme ça. (Dans sampleCls.def, def est un mot réservé et une erreur se produit (; ´∀ `))
Si vous créez une instance de cette classe dans cet état,
class sampleCls():
abc = 111
sampleCls.efg = 222
i = sampleCls()
pprint (inspect.getmembers(sampleCls))
print "------------------------------"
pprint (inspect.getmembers(i))
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
------------------------------
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
Avec ce sentiment, l'efg ajouté plus tard est également inclus dans l'instance. En passant, vous pouvez également supprimer des variables des objets de classe.
class sampleCls():
abc = 111
sampleCls.efg = 222
pprint (inspect.getmembers(sampleCls))
print "------------------------------"
del sampleCls.abc
pprint (inspect.getmembers(sampleCls))
Quand tu cours
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
------------------------------
[('__doc__', None), ('__module__', '__main__'), ('efg', 222)]
C'est parti. Cette zone est similaire à JavaScript.
Le site ci-dessous dit que python n'a pas de constructeur.
En outre, une telle chose a été écrite dans le livre. [* 1](# 1) </ sub> Quant à la définition du constructeur, il semble que l'allocation mémoire soit également faite par le constructeur.
Du point de vue de la programmation, l'allocation de mémoire est intégrée au langage, de sorte que les instances peuvent être initialisées, donc j'ai pensé qu'il serait correct de considérer init comme un constructeur général. En ce qui concerne \ __ new__, cela semble un peu différent, alors j'écrirai un peu plus ensuite.
Tout d'abord, écrivons un code simple.
class sampleCls(object):
abc = 111
print "chkpnt10"
def __new__(cls):
cls.efg = 777
print "chkpnt20"
return super(sampleCls, cls).__new__(cls)
def __init__(self):
self.hij = 999
print "chkpnt30"
pprint(dir(sampleCls))
Quand tu fais ça,
chkpnt10
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc']
chkpnt10 est sorti, mais chkpnt20 et chkpnt30 ne sont pas affichés. Ni efg ni hij ne sont inclus dans le vidage de l'objet de classe. Que se passe-t-il lorsque vous créez une instance?
class sampleCls(object):
abc = 111
print "chkpnt10"
def __new__(cls):
cls.efg = 777
print "chkpnt20"
return super(sampleCls, cls).__new__(cls)
def __init__(self):
self.hij = 999
print "chkpnt30"
i = sampleCls()
pprint (inspect.getmembers(sampleCls))
pprint (inspect.getmembers(i))
chkpnt10
chkpnt20
chkpnt30
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc',
'efg']
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc',
'efg',
'hij']
Il est sorti dans l'ordre de chkpnt10, chkpnt20, chkpnt30 (le code est en cours d'exécution). L'objet de classe contient abc et egg, mais pas hij. L'objet instance contient tous les abc, evg et hij. Le premier argument de \ __ new__ est un objet de classe, et dans le code ci-dessus, efg est défini, donc efg est ajouté à l'objet de classe en conséquence. Avec `` super (sampleCls, cls) .__ new __ (cls) '', un objet instance est créé à partir de l'objet de classe et renvoyé comme valeur de retour. La valeur de retour de \ __ new__ doit être un objet d'instance de cette classe. Si la valeur de retour est autre chose, l'objet de classe ne créera pas d'objet d'instance. init est appelé avec l'objet d'instance créé par \ __ new__ comme premier argument. Donc \ new sert à créer un objet instance à partir d'un objet de classe. Comme dans le code ci-dessus, le remplacement de \ __ new__ vous permet de modifier l'objet de classe à partir duquel l'objet d'instance est créé, et ce changement sera également reflété dans l'objet d'instance généré. D'après ce qui précède, j'ai pensé que \ __ new__ n'était pas un constructeur.
Au fait, dans la classe, ・ Type (nouvelle classe de style) et ・ Objet de classe (classe de style ancien) L'exemple ci-dessus est une nouvelle classe de style. Il semble.
Puisque j'utilise python qui est installé par défaut lorsque DataNitro est installé, ce qui précède est celui exécuté en 2.7. En 2.7, vous devez hériter d'un objet ou de quelque chose pour appeler (remplacé?) New. [* 2](# 2) </ sub> [* 3](# 3) </ sub> (Depuis la version 3.0 ou ultérieure, l'objet est hérité par défaut, il n'est donc plus nécessaire de spécifier l'héritage de la classe.)
Je me suis penché sur python ces derniers jours, et il existe un mécanisme qui permet un contrôle précis dans le programme, donc même si je me concentre sur la classe, quelque chose semble toujours flou. Vous pouvez vérifier les uns après les autres ... Mais je ne déteste pas ça. Si vous le faites, vous pourriez en être accro d'une bonne manière.
En passant, depuis la version 3.0, il y a eu des changements qui affectent le niveau d'implémentation, tels que le passage d'instructions à des expressions et l'ajout de parenthèses. Il semble que l'interface de la bibliothèque a également changé.
Je me demande si je vais continuer à étudier le python pendant un moment.
* 1. Certains livres ont peut-être init comme constructeur. Plutôt plus? * 2. J'essaye de découvrir la relation causale entre l'héritage de l'objet et l'appel de \ __ new__, et je me demande si la valeur d'attribut contrôle l'appel à \ __ new__. Je l'ai recherché, mais je ne l'ai pas trouvé. Même si le type * 3. est hérité, \ __ new__ est appelé. Cependant, dans ce cas, la signification peut être légèrement différente en raison de la relation avec la méta-classe. Futurs problèmes de recherche sur le type.