Débutant en Python, je souhaite poser une question sur la couche inférieure des types variables et des types immuables.
给我你的怀抱
给我你的怀抱 2017-06-12 09:21:12
0
4
723

Premier code :

a = "hello"   #定义一个字符串的变量
print(id(a))  #第一次的地址
print(a)      #a = hello
a = a.upper() # 单纯的a.upper() 执行过后,无法存储到a本身,必须得重新赋值给a  换句话说,a在被upper之后,重新指向了一个新的地址
print(id(a))  #第二次的地址
print(a)

Le premier résultat de l'exécution du code :

Deuxième code :

b = [11,22,33,44,55]  #定义一个列表的变量
print(id(b))          #第一次的地址
print(b)              #b = [11,22,33,44,55]
b.append(99)          #单纯的b.append()执行过后,不需要存储到b,因为b已经被更改
print(id(b))          #检查第一次的地址
print(b)              #发现在第一次地址当中,b已经改变
#b = b.append(99)     #如果将修改b这个行为赋值到b
#print(id(b))         #检查地址,发现已经变更
#print(b)             #检查b的值,发现已经变更。b的值为none   因为b.append(99)本身的返回值为none
#[***列表为可修改变量,因此修改完之后,地址跟原来的一样。反而是如果像修改字符串那样重新赋值,变得不可行。原因在于append语句本身并不返回值。***]
#字符串赋值之后放在内存一个地址,这个地址上面的字符串是无法更改的,只能重新做一个新的字符串,然后改变变量的指向位置。
#而列表赋值之后存在一个内存的地址,这个列表里面的值是可以直接修改的。不需要重新做一个新的列表,然后改变变量的指向位置。

Le deuxième résultat de l'exécution du code :

Dans le processus d'apprentissage de Python, on m'a dit que les chaînes sont des types immuables et que les listes sont des types mutables. En d’autres termes, si je veux modifier une chaîne, je crée une nouvelle chaîne et la mets dans la nouvelle adresse de la mémoire. La chaîne d’origine est toujours la même. Comme indiqué dans le premier morceau de code.
La liste est différente, la liste peut être modifiée directement à l'adresse mémoire d'origine. Comme indiqué dans le deuxième morceau de code.
Ma question :
Quelle est la différence fondamentale entre les types mutables et les types immuables ? Pourquoi cette différence se produit-elle ? Pourquoi dans le premier code, si a veut changer, il faut changer l'adresse, mais dans le deuxième code, b peut directement modifier la valeur de la liste sans changer l'adresse. Quelle est la logique sous-jacente ici ? Je me demande si cela signifie que la liste elle-même est en fait une collection de valeurs. Elle reflète simplement la collection elle-même et pointe une collection de valeurs vers cet endroit, afin qu'elle puisse être modifiée ? Je ne sais pas si je l'ai exprimé clairement.
Je suis juste très curieux à propos de cette chose. C'est-à-dire, qu'est-ce qu'une liste exactement ? Pourquoi peut-elle être modifiée directement ? La chaîne ne peut pas être modifiée. Après être allé plus loin, quels sont ces deux-là ?

给我你的怀抱
给我你的怀抱

répondre à tous(4)
大家讲道理

En fait, les objets sont mutables et immuables, ouipy, 都是内部实现的问题, 如果我修改相应的方法, 将其写回到本身, 这样也能模仿出可变的现象, 就小小类似tuplelist的关系,
既然想了解底层, 那就直接看源码吧:
这是字符串的upper()

static PyObject *
string_upper(PyStringObject *self)
{
    char *s;
    Py_ssize_t i, n = PyString_GET_SIZE(self); # 取出字符串对象中字符串的长度
    PyObject *newobj;

    newobj = PyString_FromStringAndSize(NULL, n); # 可以理解成申请内存空间
    if (!newobj)
        return NULL;

    s = PyString_AS_STRING(newobj);  # 从newobj对象取出具体字符串指针

    Py_MEMCPY(s, PyString_AS_STRING(self), n); # 拷贝旧的字符串

    for (i = 0; i < n; i++) {
        int c = Py_CHARMASK(s[i]);
        if (islower(c))
            s[i] = _toupper(c);   # 修改对应指针位置上的内容
    }

    return newobj;  # 返回新字符串对象 (区分字符串对象和里面字符串的指针)
}

Voici la listeappend

int
PyList_Append(PyObject *op, PyObject *newitem)
{
    if (PyList_Check(op) && (newitem != NULL))
        return app1((PyListObject *)op, newitem);
    PyErr_BadInternalCall();
    return -1;
}

static int
app1(PyListObject *self, PyObject *v)
{
    Py_ssize_t n = PyList_GET_SIZE(self);

    assert (v != NULL);
    if (n == PY_SSIZE_T_MAX) {
        PyErr_SetString(PyExc_OverflowError,
            "cannot add more objects to list");
        return -1;
    }

    if (list_resize(self, n+1) == -1)
        return -1;

    Py_INCREF(v);
    PyList_SET_ITEM(self, n, v);   # 因为列表是头和和成员分开的, 所以直接将新成员追加在原来的成员数组后面, 长度变化通过resize实现
    return 0;
}
巴扎黑

Les chaînes Python sont mises en cache. Si deux chaînes identiques se trouvent dans des variables a et b différentes, leur identifiant(a) et leur identifiant(b) sont identiques.
Mais si la référence de a et b est 0, l'objet sera automatiquement détruit.

Exemple d'affiche originale :

a = a.upper()

Le contenu variable de a a changé et est différent. L'ancien contenu n'a aucune référence et l'objet est détruit par le garbage collection.
b est une liste, elle est variable et vous pouvez à nouveau demander de la mémoire. En même temps, b a une référence de contenu et ne sera pas détruit.

为情所困

Allez plus loin et regardez le code source C de python~

Il peut être immuable, ce qui est stipulé par le langage python.

Les types immuables ne fournissent pas de méthodes pour modifier l'objet lui-même, tandis que les types mutables fournissent ces méthodes. Il n’y a rien de mystérieux dans ces différences.

仅有的幸福

D'un point de vue matériel, l'interface fournie aux utilisateurs est définie conformément à la réglementation et la mémoire est exploitée de manière fixe. Il n'y a ni mutabilité ni immuabilité.
En haut, il y a la couche du système d'exploitation, qui encapsule un grand nombre d'API matérielles pour enrichir les opérations des utilisateurs. L'interpréteur Python est écrit en langage C, seule la pragmatique Python est utilisée pour écrire du code. l'interprète pour l'exécution.Dans le principe ci-dessus, pour expliquer le problème actuel, la mutabilité et l'immuabilité de Python sont stipulées par le créateur de Python. La façon de mettre en œuvre ces réglementations peut être d'appeler différentes API sous-jacentes, ou différentes API sous-jacentes. mis en œuvre en les combinant. Ces dispositions sont fournies aux utilisateurs sous forme de pragmatiques Python, et finalement compilées en 0,1 pour exécution informatique. Pour les utilisateurs, les objets mutables et immuables sont une fonctionnalité fournie par le langage et peuvent compléter certaines fonctions, mais il n'y a en réalité aucune différence pour les ordinateurs.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal