2016-07-14 4 views
3

Je lis cette question, mais il ne m'a pas donné une réponse claire: How does Python interpreter look for types?Comment l'interpréteur Python fonctionne-t-il en typage dynamique?

Comment interprète python connaître le type d'une variable? Je ne cherche pas comment obtenir le type. Je suis ici en train de regarder ce qui se passe derrière la scène. Dans l'exemple ci-dessous, comment associe-t-on la classe int ou string à ma variable.

Comment sait-il c'est un entier:

>>> i = 123 
>>> type(i) 
<class 'int'> 

ou cette chaîne:

>>> i = "123" 
>>> type(i) 
<class 'str'> 
+0

@GreenAsJade: L'OP utilise Python 3, où la représentation des objets 'type' utilise' 'class'', pas''type''; ceci a été fait pour refléter que les types définis en C sont aussi des classes. –

+0

@ MartijnPieters peut-être besoin d'un tag python3 alors? – GreenAsJade

+0

@GreenAsJade: non, la réponse est la même dans Python 2 et 3. Mais la sortie fournie n'a pas besoin d'être corrigée. –

Répondre

7

comment il associe la classe int ou une chaîne à ma variable

Python ne fait pas. Les variables n'ont pas de type. Seul l'objet qu'une référence de variable a un type. Les variables sont simplement noms pointant vers des objets.

Par exemple, ce qui suit montre également le type d'un objet, mais aucune variable est impliqué:

>>> type(1) 
<class 'int'> 
>>> type('foobar') 
<class 'str'> 

Lorsque vous utilisez type(variable), la variable partie de l'expression retourne simplement l'objet que les références de nom , en passant dans l'objet à la fonction type(). Lorsque vous utilisez 1 ou 'foobar', l'expression est un littéral produisant l'objet, qui est ensuite transmis à la fonction type().

Les objets Python sont simplement des structures de données dans la mémoire de l'interpréteur; dans CPython C, les structures sont utilisées. Les variables sont simplement des références (pointeurs) à ces structures. Le type de base struct dans CPython est appelé PyObject, et cette structure a un ob_type slot qui indique à Python de quel type est quelque chose. Les types sont simplement more C structures.

Si vous voulez suivre dans le code source CPython, vous commenceriez à l'bltinmodule.c source code (depuis type est un nom intégré), qui defines type as the PyType_Type structure. Appel d'un type (type est un type aussi) invoque leur tp_new function et PyType_Typedefines that comme the type_new function. Cette fonction gère les appels avec un argument comme suit:

/* Special case: type(x) should return x->ob_type */ 
{ 
    const Py_ssize_t nargs = PyTuple_GET_SIZE(args); 
    const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds); 

    if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) { 
     PyObject *x = PyTuple_GET_ITEM(args, 0); 
     Py_INCREF(Py_TYPE(x)); 
     return (PyObject *) Py_TYPE(x); 
    } 

Ici x est l'objet PyObject que vous avez passé dans; notez, pas une variable, mais un objet! Ainsi, pour votre objet entier 1 ou 'foobar' objet chaîne, le résultat macro Py_TYPE() est renvoyé. Py_TYPE is a macro qui renvoie simplement la valeur ob_type de toute struct PyObject. Donc maintenant vous avez l'objet type pour 1 ou 'foobar'; comment se fait-il que vous voyez <class 'int'> ou <class 'str'> dans votre session d'interprète? L'interpréteur interactif Python utilise automatiquement le repr() function sur les résultats d'expression. Dans la structure C pour les définitions PyType_Type, la structure PyType_Type est incorporée de sorte que tous les emplacements pour ce type sont directement disponibles; Je vais omettre ici exactement comment fonctionne . Pour les objets de type, en utilisant repr() signifie que le type_repr function est appelé qui retourne ceci:

rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name); 

Donc à la fin, type(1) obtient la fente ->ob_type, (qui se révèle être le PyLong_Type struct en Python 3, longue histoire), et cette structure a un tp_name slot set to "int".

TL; DR: Les variables Python n'ont aucun type, elles sont simplement des pointeurs vers des objets. Les objets ont des types, et l'interpréteur Python suivra une série de références indirectes pour atteindre le nom de type à imprimer si vous faites écho à l'objet dans votre interpréteur.

0

Le concept « type » d'une variable est « mis en oeuvre » en utilisant des objets d'une classe spécifique .

Ainsi, dans

a=float()

un objet de type float, tel que défini par la classe float est retournée par float(). Python sait de quel type il s'agit parce que c'est comme ça que les objets fonctionnent: vous savez de quel type ils sont. a est maintenant un objet float, avec une valeur de 0.0.

Avec les builtins, c'est pareil, c'est juste qu'ils ont des raccourcis pour les déclarer.

i=123

est le même que

i=int(123)

int() retourne un objet de classe de nombre entier, avec la valeur 123.

similaire

i="123"

est le même que

i=str("123")

str("123") retourne un objet de la classe str, avec la valeur "123"

0

Les variables Python n'ont aucun type, elles ne sont que des références aux objets. La taille d'une référence est la même indépendamment de ce à quoi elle fait référence.Dans l'implémentation C de Python c'est un pointeur, et a a un type, c'est un pointeur vers un objet Python: PyObject *. Le pointeur est le même type indépendamment de la classe d'objet. Les objets, d'autre part, savent à quelle classe ils appartiennent.

Il a été soutenu que Python n'a pas de variables, seulement des noms, bien que ce soit un pas trop loin pour la plupart des gens.

Les références dans l'implémentation de CPython ont un identifiant (identifiant) qui est en réalité une adresse virtuelle. Le détail et la valeur de cette adresse ne valent pas la peine d'être poursuivis - elle peut (et va probablement) changer entre les versions et n'est pas destinée à être utilisée pour autre chose qu'un numéro unique identifiant l'objet. Néanmoins, il peut fournir des indications intéressantes (pardonnez le jeu de mots) à ce qui se passe:

>>> x = 42 
>>> y = x 
>>> id(x) 
4297539264 
>>> id(y) 
4297539264 

Notez que l'identifiant (adresse) de x et y sont les mêmes - ils font référence à un même objet, un int avec la valeur 42. Que se passe-t-il lorsque nous changeons x, y change-t-il également?

>>> x = "hello" 
>>> id(x) 
4324832176 
>>> id(y) 
4297539264 

Heureusement pas. Maintenant, x fait simplement référence à un nouvel objet de la classe str avec la valeur "Hello".

Quand nous:

>>> id(y) 
4297539264 
>>> y = 37 
>>> id(y) 
4297539104 

L'ID de y changé! C'est parce qu'il fait maintenant référence à un objet différent. int s sont immutable, de sorte que l'affectation y = 37 n'a pas changé l'objet original (42), il a créé un nouveau. L'objet avec la valeur 42 a son compte de référence décrémenté et peut maintenant (en théorie) être supprimé. En pratique, il restera probablement en mémoire pour des raisons d'efficacité, mais c'est un détail d'implémentation.

Cependant:

>>> a = [1,2,3,4] 
>>> b = a 
>>> id(a) 
4324804808 
>>> id(b) 
4324804808 
>>> a[0] = 99 
>>> b 
[99, 2, 3, 4] 

Donc changer la liste aa changé b! C'est parce que les listes sont mutable, elles peuvent changer. L'affectation b = a n'a copié que la référence, pas la liste. Voir copy dans la bibliothèque standard.