ProgrammatiePython middle/senior ontwikkelaar

Vertel over het gebruik en de toepassing van de functies partial en partialmethod uit het functools-module. Wat is het verschil tussen hen, waarom gebruiken bij het ontwerpen van code, en wat zijn de kenmerken van hun gebruik?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Geschiedenis van de vraag

De functie partial is geïntroduceerd in de standaard bibliotheek van Python (functies in het module functools) vanaf Python 2.5, om het patroon van currying en gedeeltelijke argumenttoepassing op functies te implementeren. partialmethod verscheen met Python 3.4 voor een vergelijkbare toepassing in klassenmethoden.

Probleem

Vaak vereist de praktijk in echte projecten het vastzetten van een deel van de argumenten van een functie, om een nieuwe functie te krijgen met "opgeslagen" waarden voor bepaalde argumenten. Dit is handig voor callbacks, argumentoverdrachtsjablonen, of voor het verbeteren van de leesbaarheid van de code, vooral in functioneel programmeren en bij het gebruik van API's die een bepaalde functionele stijl verwachten.

Oplossing

De functie partial retourneert een nieuw functie-object, waarin bepaalde doorgegeven argumenten of sleutelargumenten "hardcoded" (vastgelegd) zijn. partialmethod implementeert dezelfde aanpak voor klassenmethoden, waarbij de self/cls-mechaniek correct wordt ondersteund.

Voorbeeldcode:

from functools import partial, partialmethod def power(base, exponent): return base ** exponent # Vastzetten van exponent = 2 square = partial(power, exponent=2) print(square(5)) # 25 class Math: def power(self, base, exponent): return base ** exponent square = partialmethod(power, exponent=2) m = Math() print(m.square(5)) # 25

Belangrijke kenmerken:

  • partial creëert een nieuwe functie met ingebouwde (gevoegde) waarden voor een deel van de argumenten.
  • partialmethod is een vergelijkbare constructie voor klassenmethoden, werkt correct met self/cls.
  • Verbetert de leesbaarheid, stelt gebruikers in staat om "functionele wrappers" en callbacks met vaste parameters te maken.

Vragen met een valstrik.

Kan partial worden gebruikt voor klassenmethoden om een equivalente partialmethod te krijgen?

Nee, partial behandelt self/cls niet correct, het werkt niet zoals verwacht wanneer het op een klassenmethode wordt toegepast: self wordt niet automatisch ingevuld.

class C: def m(self, x, y): return x + y wrong = partial(m, y=2) # Fout!

Bij het aanroepen van c.wrong(5) zal een TypeError optreden, omdat self niet automatisch wordt doorgegeven.

Is het object dat via partial is gemaakt een functie?

Ja, het resultaat van partial is een object dat zich gedraagt als een functie, ondersteunt aanroepen, naam, docstring, enz., maar dit is geen gewone functie, dit is een object van de partial-klasse die het call-protocol implementeert.

from functools import partial f = partial(pow, 2) print(type(f)) # <class 'functools.partial'>

Werkt partial met standaardargumenten van functies?

Ja, partial kan de standaardwaarden in de interne functie "overschrijven"; als argumenten aan partial worden doorgegeven, hebben deze voorrang boven de standaardwaarden in de functie zelf. Het is echter belangrijk om geen waarden te dupliceren, anders zal er een fout optreden.

Veelvoorkomende fouten en antipatterns

  • partial toepassen op bound-methoden en verwachten dat de juiste self wordt verkregen — werkt niet, gebruik partialmethod.
  • Te laat of onjuiste waarden van vaste argumenten doorgeven — er zal een fout optreden bij het aanroepen.
  • De structuur van de code verwarren door partial te misbruiken voor triviale functies.

Voorbeeld uit het leven

Negatieve case

Een ontwikkelaar gebruikt partial voor een klassenmethode in plaats van partialmethod:

class MyClass: def f(self, x, y): ... squared = partial(f, y=2) ... obj = MyClass() obj.squared(5) # TypeError: ontbreekt 1 vereist positioneel argument: 'self'

Voordelen:

  • De code ziet er elegant uit.

Nadelen:

  • Werkt niet met de "magie" van self- doorgeven.
  • De fout verschijnt pas tijdens runtime.

Positieve case

In plaats daarvan wordt partialmethod gebruikt:

from functools import partialmethod class MyClass: def f(self, x, y): return x + y squared = partialmethod(f, y=2) obj = MyClass() print(obj.squared(5)) # 7

Voordelen:

  • Werkt zoals verwacht.
  • De code is leesbaar en schaalbaar.

Nadelen:

  • Vereist kennis van de mogelijkheden van partialmethod (niet voor beginners).