ProgrammatieMiddle Python ontwikkelaar

Hoe werkt de 'in' operator voor gebruikersobjecten in Python? Wat moet er in de klasse worden geïmplementeerd zodat de expressie 'x in your_obj' werkt? Hoe kunnen prestaties en onverwachte fouten worden vermeden?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

De 'in' operator in Python bepaalt of een element zich in een collectie bevindt. Voor gebruikersobjecten, om de constructie 'x in your_obj' te ondersteunen, moet de methode __contains__ worden geïmplementeerd. Als deze er niet is, zal de interpreter proberen het object te itereren met behulp van __iter__ of __getitem__, maar het gedrag en de efficiëntie kunnen verschillen.

Voorbeeld:

class MyBag: def __init__(self, items): self.items = items def __contains__(self, value): return value in self.items bag = MyBag([1,2,3]) print(2 in bag) # True print(5 in bag) # False

Als je alleen __iter__ (of zelfs alleen __getitem__) implementeert, zal in werken, maar minder efficiënt en soms helemaal niet zoals verwacht.

Let op: als de collectie enorm is en de controle naïef is geïmplementeerd (bijvoorbeeld door een loop door de hele lijst), kunnen er prestatieproblemen zijn. Voor snelle controles worden bijvoorbeeld verzamelingen gebruikt.

Misleidende vraag.

Is het voldoende om alleen __iter__ of alleen __getitem__ te implementeren voor de correcte werking van de 'in' operator? Hoe verandert het gedrag?

Antwoord:

  • Als er geen __contains__ is, zal Python proberen de elementen te doorlopen met __iter__ (als deze er is) of __getitem__ (beginnende met index 0, totdat er een IndexError wordt gegooid).
  • Dit gedrag is minder efficiënt en kan eindeloze lussen of uitzonderingen veroorzaken als de methoden met typefouten zijn geïmplementeerd.

Voorbeeld:

class Weird: def __getitem__(self, idx): if idx < 3: return idx raise IndexError w = Weird() print(2 in w) # True print(5 in w) # False

Voorbeelden van echte fouten door gebrek aan kennis van de nuances van dit onderwerp.


Verhaal

In een project had een gebruikerscontainer voor entiteiten alleen __iter__ overschreven, daarbij vergeten __contains__ te implementeren. De 'in' operator begon niet alleen traag te werken (voor grote collecties waren er vertragingen merkbaar), maar viel ook plotseling met mysterieuze fouten wanneer de iterator ten onrechte uitzonderingen gooide die geen StopIteration waren.


Verhaal

Voor een klasse, waarin elementen "on-the-fly" werden berekend op basis van index, had de ontwikkelaar alleen __getitem__ geïmplementeerd. Bij de poging om 'x in obj' met een grote x te controleren, ontstonden lange lussen en zelfs Out Of Memory — want 'in' controleert alle indices in stijgende volgorde totdat het een IndexError tegenkomt.


Verhaal

In een van de projecten was een aangepaste woordenboekomde die voor 'in' alleen op __iter__ steunde. Dit leidde ertoe dat het zoeken naar 100.000 sleutels seconden duurde in plaats van milliseconden bij de standaard dict (waarbij __contains__ efficiënt is geïmplementeerd).