Как назначить None для ссылки на объект в Python - PullRequest
0 голосов
/ 14 ноября 2018

Я новичок в python, немного запутался по поводу вывода следующего кода.

class obj:
    def __init__(self, data):
            self.data = data

o1 = obj(2)
o2 = o1

def func1(obj):
    obj.data = 5


func1(o1)
print(o1.data)
print(o2.data)
o2 = None
print(o1)
print(o2)

Выход:

5
5
<__main__.obj instance at 0x7f7f6b5e63f8>
None

Разве объект o1 тоже не должен становиться 'None' ??

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Строка o2 = None эффективно переназначается как объект, отличный от o1.Наблюдайте:

>>> o1 = obj(2)
>>> id(o1)
155034832  
>>> o2 = o1
>>> id(o2)
155034832  # same ID as o1
>>> o1 is o2
True       # the objects are identical

Но как только вы переназначите o2:

>>> o2 = None
>>> id(o2)
262150788  # ID has now changed
>>> o1 is o2
False      # the objects are now different.

После переназначения объекты не будут иметь отношения друг к другу (если они не связаны другими способами), и разумно выне следует ожидать, что они будут вести себя одинаково.

0 голосов
/ 14 ноября 2018

Переменные в Python - это имена объектов , а не места памяти , как в C ++. Переназначение имени просто меняет то, к чему относится имя; он не меняет референт или другие псевдонимы.


Ближайшим эквивалентом является указатель: в CPython присвоение имени, как в o2 = o1, фактически означает PyObject *o2 = *o1. Адрес скопирован с одного имени на другое. Не существует прямой связи между именами после присваивания - они просто все еще ссылаются на один и тот же объект.

>>> o1 = {1, 2, 3}
>>> o2 = o1
>>> print(id(o1), id(o2))  # the *referents* of o1 and o2 are at the same memory location
4444160520 4444160520

Когда два имени относятся к одному и тому же объекту, они показывают одно и то же состояние объекта - в конце концов, существует только одно состояние. Вот почему изменение o1.data было видно также и через o2 - объект , на который ссылаются как o2, так и o1, был изменен.

>>> o1.add(16)
>>> print(o1, o2)  # still the same referent, should have the same state
{16, 1, 2, 3} {16, 1, 2, 3}
>>> print(id(o1), id(o2))  # both still have the same referent
4444160520 4444160520

Хитрость в том, что хотя o1 и o2 являются отдельными, такие члены, как o1.data и o2.data не являются! Каждое имя верхнего уровня является отдельной сущностью. Однако атрибуты и тому подобное относятся к их объекту!


При переназначении изменяется только имя, назначенное для. Помните, что o2 скопировал ссылку из o1 - нет никакого отношения, на которое может повлиять изменение имени o1.

>>> o1 = None
>>> print(o1, o2)  # not the same referent anymore
None {16, 1, 2, 3}
>>> print(id(o1), id(o2))  # only o2 still refers to the same referent
4436169032 4444160520
0 голосов
/ 14 ноября 2018

o1 не должно быть None.

при выполнении строки o2 = None, o2 больше не ссылается на объект o1. Теперь это относится к объекту None. o1 и o2 теперь ссылаются на два разных объекта в памяти, как показано функцией id (разные идентификаторы, id возвращает адрес памяти объекта в CPython)

print (id(o1)) # 140282748479024
print (id(o2)) # 140282748479024
o2 = None
print (id(o1)) # 140282748479024
print (id(o2)) # 140282774063376
...