Python Academy · Oppitunti

CPythonin viitelaskenta

Ymmärtäkää, miten CPython seuraa olioiden elinikää viitelaskureilla.

Oppitunti 1/413 vaihetta

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))   # 3

sys.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 baseline

Kasvattaminen 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 → deallocated

Olioiden 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 them

gc-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 collected

Muistipoolit (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-enable

Pikatarkistus

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.

Aloita maksutta

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

  1. CPythonin viitelaskenta
  2. Roskienkerääjä ja sykliset viittaukset
  3. Profilointi cProfilella ja line_profilerilla
  4. Muistiprofilointi tracemallocilla
← Takaisin: Python Academy