Какие типы объектов Python инициализируются ссылкой, а какие нет? - PullRequest
3 голосов
/ 07 июня 2019

Я играл с sys.getrefcount в Python 3.7 на Windows.Я попробовал следующее:

>>> import sys
>>> x = "this is an arbitrary string"
>>> sys.getrefcount(x)
2

Я понимаю, что одна из ссылок - x, а другая - параметр, используемый внутри sys.getrefcount.Кажется, это работает независимо от типа, к которому инициализируется x.Тем не менее, я заметил странное поведение, когда я не назначаю перед передачей:

>>> import sys
>>> sys.getrefcount("arbitrary string")
2
>>> sys.getrefcount(1122334455)
2
>>> sys.getrefcount(1122334455+1)
2
>>> sys.getrefcount(frozenset())
2
>>> sys.getrefcount(set())
1
>>> sys.getrefcount(object())
1
>>> sys.getrefcount([])
1
>>> sys.getrefcount(lambda x: x)
1
>>> sys.getrefcount(range(1122334455))
1
>>> sys.getrefcount(dict())
1
>>> sys.getrefcount(())
8341
>>> sys.getrefcount(tuple())
8340
>>> sys.getrefcount(list("arbitrary string"))
1
>>> sys.getrefcount(tuple("arbitrary string"))
1
>>> sys.getrefcount(("a", "r", "b", "i", "t", "r", "a", "r", "y", " ", "s", "t", "r", "i", "n", "g"))
2

Что здесь происходит?Кажется, что неизменяемые типы имеют две ссылки, а изменяемые - только одну?Почему кажется, что некоторые объекты присваиваются перед передачей, в то время как другие имеют ссылку только в качестве параметра?Имеет ли это какое-то отношение к str / int / tuple internment?

Редактировать: Более направленный вопрос: почему было выбрано, что неизменяемые типы, такие как frozenset(), имеют ссылку на конструкцию,в то время как изменяемые типы, такие как set() нет?Я понимаю по отдельности, почему вы можете оставить эту ссылку глобальной области действия или нет, но почему это расхождение?

1 Ответ

1 голос
/ 07 июня 2019

Интересный вопрос, так что вот интересный read .

Вы должны попробовать getrefcount(2), для меня он вернул 93, что означает, что CPython хранит 93 ссылки на один и тот же адрес памятиоставляя номер два, чтобы ему не приходилось распределять его снова, и, поскольку он неизменен, это вполне нормально.

Теперь давайте попробуем две разные вещи:

# first
getrefcount(set()) # returns 1

# second
s = set()
getrefcount(s) # returns 2

Поскольку это изменяемые типы, его поведение отличается при создании изменяемого типа (set()), он будет выделять его в памяти и иметь только одну ссылку на него, которая будет удалена сразу после конца этой строки.Но на втором мы определяем переменную, и она распределяет ее, при подсчете ссылок у нас есть одна, используемая s, и та, которая используется внутри функции getrefcount.

И в Python кортежи неизменны , по этой причине он возвращает огромное количество, CPython хранит множество ссылок на пустой кортеж.

...