Istnieje kilka scenariuszy, które przyniosą inną liczbę referencyjną. Najprostszym jest konsola REPL:
>>> import sys
>>> the_var = 'Hello World!'
>>> print(sys.getrefcount(the_var))
2
Zrozumienie ten wynik jest całkiem prosta - jest jedna wzmianka w lokalnej stosu i kolejna tymczasowa/local do funkcji sys.getrefcount()
(nawet documentation ostrzega o tym - The count returned is generally one higher than you might expect
). Ale kiedy go uruchomić jako samodzielny skryptu:
import sys
the_var = 'Hello World!'
print(sys.getrefcount(the_var))
# 4
jak zauważyłeś, masz 4
. Co daje? Dobrze, pozwala zbadać ... Jest to bardzo pomocne interfejs do śmieciarza - moduł gc
- więc jeśli uruchomić go w konsoli REPL:
>>> import gc
>>> the_var = 'Hello World!'
>>> gc.get_referrers(the_var)
[{'__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'the_var': 'Hello
World!', 'gc': <module 'gc' (built-in)>, '__name__': '__main__', '__doc__': None}]
Brak cuda tam - to w zasadzie tylko prąd namespace (locals()
) ponieważ zmienna nie istnieje nigdzie indziej. Ale co się dzieje, gdy prowadzimy że jako samodzielny skryptu:
import gc
import pprint
the_var = 'Hello World!'
pprint.pprint(gc.get_referrers(the_var))
ten drukuje (YMMV, na podstawie swojej wersji Pythona):
[['gc',
'pprint',
'the_var',
'Hello World!',
'pprint',
'pprint',
'gc',
'get_referrers',
'the_var'],
(-1, None, 'Hello World!'),
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'test.py',
'__name__': '__main__',
'__package__': None,
'gc': <module 'gc' (built-in)>,
'pprint': <module 'pprint' from 'D:\Dev\Python\Py27-64\lib\pprint.pyc'>,
'the_var': 'Hello World!'}]
Rzeczywiście, mamy jeszcze dwie referencje z listy tak jak nam powiedział sys.getrefcount()
, ale co to do cholery jest? Cóż, kiedy interpreter Pythona analizuje twój skrypt, najpierw musi on być compile podłączony do kodu bajtowego - i podczas gdy on to robi, przechowuje wszystkie łańcuchy na liście, która, ponieważ wspomina również twoją zmienną, jest zadeklarowana jako odniesienie do niej.
Drugi bardziej tajemniczy wpis ((-1, None, 'Hello World!')
) pochodzi z peep-hole optimizer i tam właśnie właśnie optymalizuje dostęp (w tym przypadku odwołanie do łańcucha).
Oba te mają charakter tymczasowy i opcjonalnie - konsola REPL robi separację kontekstowe więc nie widzisz tych odniesień, jeśli były do „outsourcingu” swoją kompilację ze swojej obecnej sytuacji:
import gc
import pprint
exec(compile("the_var = 'Hello World!'", "<string>", "exec"))
pprint.pprint(gc.get_referrers(the_var))
ty „d dostać:
[{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'test.py',
'__name__': '__main__',
'__package__': None,
'gc': <module 'gc' (built-in)>,
'pprint': <module 'pprint' from 'D:\Dev\Python\Py27-64\lib\pprint.pyc'>,
'the_var': 'Hello World!'}]
a jeśli były, aby wrócić do oryginalnego próbę uzyskania licznika odwołań poprzez sys.getreferencecount()
:
import sys
exec(compile("the_var = 'Hello World!'", "<string>", "exec"))
print(sys.getrefcount(the_var))
# 2
podobnie jak w konsoli REPL i zgodnie z oczekiwaniami. Dodatkowe odniesienie ze względu na optymalizację peep-hole, ponieważ dzieje się to w miejscu, może być natychmiast odrzucone przez wymuszenie zbierania śmieci (gc.collect()
) przed zliczeniem referencji.
Jednak lista napisów utworzona podczas kompilacji nie może zostać zwolniona, dopóki cały plik nie zostanie przeanalizowany i skompilowany, dlatego jeśli miałbyś zaimportować swój skrypt do innego skryptu, a następnie policzyć odniesienia do niego the_var
dostaniesz 3
zamiast 4
właśnie wtedy, gdy myślałeś, że już nie może ci to zmylić;)
Czy piszesz to od razu w powłoce Pythona lub Pythona? lub uruchamiając go jako samodzielny skrypt? Dostaję 2 referencje w zwykłej powłoce Pythona. – Meitham
Po uruchomieniu kodu w wersji 2.7.13 otrzymuję "Var created: 2 references'. – Alex
Spodziewałbym się 2 referencji w trybie interaktywnym i 3 jako skryptu (jeden dodatkowy dla odniesienia ze stałych obiektu kodu), ale nie 4. Możliwe, że zrobiłeś coś innego, aby utworzyć inne odniesienie. – user2357112