CPythonin viitelaskenta
Ymmärtäkää, miten CPython seuraa olioiden elinikää viitelaskureilla.
CPythonin viitelaskenta on ilmainen Python Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Python Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Python Academy-kurssilla on yhteensä 4 oppituntia.
Mitä viitelaskenta tarkoittaa?
CPython seuraa jokaisen olion viitemäärää. Kun määrä laskee nollaan, olio vapautetaan välittömästi. Tämä on Pythonin ensisijainen muistinhallintamekanismi.
import sys
x = [1, 2, 3]
print(sys.getrefcount(x)) # 2 (x + getrefcount arg)
y = x
print(sys.getrefcount(x)) # 3sys.getrefcount()
sys.getrefcount(obj) palauttaa nykyisen viitemäärän. Huomaa, että kutsu lisää määrää yhdellä, koska funktion argumentti muodostaa yhden viitteen.
import sys
a = "hello"
print(sys.getrefcount(a)) # baseline (may be high for interned strings)
b = a
print(sys.getrefcount(a)) # one more
del b
print(sys.getrefcount(a)) # back to baselineKasvattaminen ja pienentäminen
Jokainen sijoitus kasvattaa viitemäärää, ja jokainen poisto tai uusi sijoitus pienentää sitä. Kun määrä saavuttaa nollan, CPython kutsuu olion vapautusfunktiota.
x = [] # refcount = 1
y = x # refcount = 2
z = [x] # refcount = 3 (list holds a reference)
del y # refcount = 2
z.clear() # refcount = 1
del x # refcount = 0 → deallocatedOlioiden interning
CPython pitää pienet kokonaisluvut (-5–256) ja monet merkkijonoliteraalit internoinnissa ja käyttää samaa oliota uudelleen. is-vertailut paljastavat tämän.
a = 256
b = 256
print(a is b) # True (interned)
c = 257
d = 257
print(c is d) # may be False (not interned)Heikot viitteet
Heikot viitteet eivät kasvata viitemäärää. Niistä on hyötyä, kun haluatte tarkkailla olioita omistamatta niitä ja estämättä niiden roskienkeruuta.
import weakref
class BigObject:
pass
obj = BigObject()
ref = weakref.ref(obj)
print(ref()) # <BigObject instance>
del obj
print(ref()) # None (object was collected)Viittauskehät
Jos A viittaa B:hen ja B A:han, kumpikaan ei saavuta viitemäärää nolla, vaikka molempiin ei olisi enää viitteitä. CPythonin syklinen roskienkerääjä havaitsee ja kerää nämä oliot.
a = []
b = [a]
a.append(b) # cycle: a → b → a
del a, b
# Both are unreachable but refcount > 0
# The cyclic GC collects themgc-moduuli
gc-moduuli tarjoaa syklisen roskienkerääjän. Se toimii automaattisesti, mutta sen voi käynnistää myös manuaalisesti tai poistaa käytöstä.
import gc
gc.collect() # force a collection cycle
print(gc.get_count()) # (gen0, gen1, gen2) allocation counts
print(gc.get_threshold()) # when each generation is collectedMuistipoolit (pymalloc)
CPython varaa pienet oliot (alle 512 tavua) omasta muistipoolistaan (pymalloc), joka on nopeampi kuin malloc-kutsun tekeminen jokaiselle pienelle oliolle.
# You do not call pymalloc directly — CPython uses it internally
# for all Python-level object allocations
# The pool pre-allocates large memory arenas
# and carves them into pools of fixed-size blocks__del__-viimeistelijät
__del__ kutsutaan, kun olion viitemäärä saavuttaa nollan, tai myöhemmin, jos olio kuuluu viittauskehään. Älkää luottako siihen tärkeässä siivouksessa — käyttäkää sen sijaan kontekstinhallitsijoita.
class Resource:
def __del__(self):
print(f"Freeing {self}")
# Better: use context manager
class SafeResource:
def __enter__(self): return self
def __exit__(self, *a): self.cleanup()Kompaktit oliot __slots__-määritteellä
__slots__-määritettä käyttävät oliot tarvitsevat vähemmän muistia ja muistivarauksia, mikä vähentää roskienkeräimen kuormitusta.
import sys
class Reg:
def __init__(self, x, y): self.x, self.y = x, y
class Slotted:
__slots__ = ("x","y")
def __init__(self, x, y): self.x, self.y = x, y
print(sys.getsizeof(Reg(1,2))) # ~48 + dict overhead
print(sys.getsizeof(Slotted(1,2))) # ~48 (no dict)Syklisen roskienkeruun poistaminen käytöstä
Ohjelmissa, jotka eivät luo viittauskehiä, syklisen roskienkeruun poistaminen käytöstä voi parantaa läpimenoa.
import gc
gc.disable() # no cyclic GC — objects are only freed by refcounting
# Use only if you KNOW no cycles are created
# (pure functional/immutable data)
gc.enable() # re-enablePikatarkistus
Milloin CPython vapauttaa olion välittömästi?
Kertaus
CPython seuraa olioita viitemäärien avulla. Kun määrä saavuttaa nollan, olio vapautetaan välittömästi. Syklinen roskienkerääjä (gc-moduuli) käsittelee viittauskehät. Välttäkää __del__-määritettä tärkeässä siivouksessa ja käyttäkää kontekstinhallitsijoita. Käyttäkää __slots__-määritettä oliokohtaisen muistin vähentämiseen.
Opi Python tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 76
- Oppitunnit
- 320
Usein kysytyt kysymykset
Onko oppitunti ”CPythonin viitelaskenta” ilmainen?
Kyllä – oppitunnin ”CPythonin viitelaskenta” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Python Academy-kurssin, päivitä CoddyKit PROhon. Python Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”CPythonin viitelaskenta”?
Ymmärtäkää, miten CPython seuraa olioiden elinikää viitelaskureilla. Harjoittelet Python Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Python Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Python Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.
Kuinka kauan ”CPythonin viitelaskenta”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Python Academy-oppitunnilla?
Kyllä. Jokainen Python Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- CPythonin viitelaskenta
- Roskienkerääjä ja sykliset viittaukset
- Profilointi cProfilella ja line_profilerilla
- Muistiprofilointi tracemallocilla