Zephyrnet-logo

8 ingebouwde Python-decorateurs om elegante code te schrijven – KDnuggets

Datum:

8 ingebouwde Python-decorateurs om elegante code te schrijven
Afbeelding door redacteur
 

Python is, met zijn duidelijke en leesbare syntaxis, een veelgebruikte programmeertaal op hoog niveau. Python is ontworpen met het oog op gebruiksgemak, waarbij de nadruk wordt gelegd op eenvoud en lagere kosten voor programma-onderhoud. Het wordt geleverd met een uitgebreide bibliotheek die de noodzaak voor ontwikkelaars om vanaf het begin code te schrijven vermindert en de productiviteit van ontwikkelaars verhoogt. Een krachtig kenmerk van Python dat bijdraagt ​​aan code-elegantie zijn decorateurs.

In Python is een decorateur een functie waarmee je het gedrag van een andere functie kunt wijzigen zonder de kernlogica ervan te veranderen. Het neemt een andere functie als argument en retourneert de functie met uitgebreide functionaliteit. Op deze manier kunt u decorateurs gebruiken om wat extra logica aan bestaande functies toe te voegen en de herbruikbaarheid met slechts een paar regels code te vergroten. In dit artikel zullen we acht ingebouwde Python-decorateurs verkennen die u kunnen helpen elegantere en onderhoudbare code te schrijven.

 

8 ingebouwde Python-decorateurs om elegante code te schrijven
Afbeelding door redacteur

De @atexit.register decorateur wordt gebruikt om een ​​functie te registreren die moet worden uitgevoerd bij het beëindigen van het programma. Deze functie kan worden gebruikt om elke taak uit te voeren wanneer het programma op het punt staat af te sluiten, ongeacht of dit het gevolg is van een normale uitvoering of van een onverwachte fout.

Voorbeeld:

import atexit

# Register the exit_handler function
@atexit.register
def exit_handler():
    print("Exiting the program. Cleanup tasks can be performed here.")

# Rest of the program
def main():
    print("Inside the main function.")
    # Your program logic goes here.

if __name__ == "__main__":
    main()

Output:

Inside the main function.
Exiting the program. Cleanup tasks can be performed here.

 

In de bovenstaande implementatie @atexit.register wordt boven de functiedefinitie vermeld. Het definieert de exit_handler() fungeren als exitfunctie. In wezen betekent dit dat wanneer het programma zijn eindpunt bereikt, hetzij door normale uitvoering, hetzij door een onverwachte fout die een voortijdige afsluiting veroorzaakt, het programma het eindpunt bereikt. exit_handler() functie zal worden aangeroepen.

De @dataclasses.dataclass is een krachtige decorateur die wordt gebruikt om automatisch algemene speciale methoden te genereren voor klassen zoals “__init__”, “__repr__” en andere. Het helpt u schonere, beknoptere code te schrijven door de noodzaak te elimineren om standaardmethoden te schrijven voor het initialiseren en vergelijken van instanties van uw klasse. Het kan ook helpen fouten te voorkomen door ervoor te zorgen dat algemene speciale methoden consistent in uw codebase worden geïmplementeerd.

Voorbeeld:

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int


point = Point(x=3, y=2)
# Printing object
print(point)

# Checking for the equality of two objects
point1 = Point(x=1, y=2)
point2 = Point(x=1, y=2)
print(point1 == point2)

Output:

Point(x=3, y=2)
True

 

De @dataclass decorateur, toegepast boven de klassedefinitie Point, signaleert Python om standaardgedrag te gebruiken voor het genereren van speciale methoden. Hierdoor wordt automatisch de __init__ methode, die klassekenmerken, zoals x en y, initialiseert bij het instantiëren van objecten. Als gevolg hiervan kunnen instanties als point worden geconstrueerd zonder dat expliciete codering nodig is. Bovendien is de __repr__ De methode, die verantwoordelijk is voor het leveren van een stringrepresentatie van objecten, wordt ook automatisch aangepast. Dit zorgt ervoor dat wanneer een object, zoals een punt, wordt afgedrukt, dit een duidelijke en geordende weergave oplevert, zoals te zien in de uitvoer: Point(x=3, y=2). Bovendien levert de gelijkheidsvergelijking (==) tussen twee instanties, punt1 en punt2, True op. Dit is opmerkelijk omdat Python standaard controleert op gelijkheid op basis van de geheugenlocatie. In de context van dataclass-objecten wordt de gelijkheid echter bepaald door de gegevens die zich daarin bevinden. Dit komt omdat de @dataclass-decorateur een __eq__ methode die controleert op de gelijkheid van de gegevens in de objecten, in plaats van te controleren op dezelfde geheugenlocatie.

De @enum.unique decorateur, te vinden in de enum-module, wordt gebruikt om ervoor te zorgen dat de waarden van alle leden van een opsomming uniek zijn. Dit helpt voorkomen dat er per ongeluk meerdere opsommingsleden met dezelfde waarde worden aangemaakt, wat tot verwarring en fouten kan leiden. Als er dubbele waarden worden gevonden, a ValueError wordt verhoogd.

Voorbeeld:

from enum import Enum, unique

@unique
class VehicleType(Enum):
    CAR = 1
    TRUCK = 2
    MOTORCYCLE = 3
    BUS = 4

# Attempting to create an enumeration with a duplicate value will raise a ValueError
try:
    @unique
    class DuplicateVehicleType(Enum):
        CAR = 1
        TRUCK = 2
        MOTORCYCLE = 3
        # BUS and MOTORCYCLE have duplicate values
        BUS = 3
except ValueError as e:
    print(f"Error: {e}")

 

Output:

Error: duplicate values found in : BUS -> MOTORCYCLE

 

In de bovenstaande implementatie hebben “BUS” en “MOTORFIETS” dezelfde waarde “3”. Als gevolg hiervan is de @unique decorateur genereert een ValueError met een bericht dat aangeeft dat er dubbele waarden zijn gevonden. U kunt dezelfde sleutel niet meer dan één keer gebruiken, noch kunt u dezelfde waarde aan verschillende leden toekennen. Op deze manier helpt het dubbele waarden voor meerdere opsommingsleden te voorkomen.

De partial decorateur is een krachtig hulpmiddel dat wordt gebruikt om deelfuncties te creëren. Met gedeeltelijke functies kunt u enkele argumenten van de oorspronkelijke functie vooraf instellen en een nieuwe functie genereren met die argumenten al ingevuld.

Voorbeeld:

from functools import partial

# Original function
def power(base, exponent):
    return base ** exponent

# Creating a partial function with the exponent fixed to 2
square = partial(power, exponent=2)

# Using the partial function
result = square(3)
print("Output:",result)

 

Output:

 

In de bovenstaande implementatie hebben we een functie “macht” die twee argumenten “basis” en “exponent” accepteert en het resultaat retourneert van het grondtal verheven tot de macht van exponent. We hebben een gedeeltelijke functie gemaakt met de naam “vierkant” met behulp van de originele functie waarin de exponent vooraf is ingesteld op 2. Op deze manier kunnen we de functionaliteit van originele functies uitbreiden met behulp van een partial decorateur.

De @singledisptach decorateur wordt gebruikt om generieke functies te creëren. Hiermee kunt u verschillende implementaties definiëren van functies met dezelfde naam maar met verschillende argumenttypen. Dit is met name handig als u wilt dat uw code zich anders gedraagt ​​voor verschillende gegevenstypen.

Voorbeeld:

from functools import singledispatch

# Decorator
@singledispatch
def display_info(arg):
    print(f"Generic: {arg}")

# Registering specialized implementations for different types
@display_info.register(int)
def display_int(arg):
    print(f"Received an integer: {arg}")

@display_info.register(float)
def display_float(arg):
    print(f"Received a float: {arg}")

@display_info.register(str)
def display_str(arg):
    print(f"Received a string: {arg}")

@display_info.register(list)
def display_sequence(arg):
    print(f"Received a sequence: {arg}")

# Using the generic function with different types
display_info(39)             
display_info(3.19)          
display_info("Hello World!")
display_info([2, 4, 6])     

 

Output:

Received an integer: 39
Received a float: 3.19
Received a string: Hello World!
Received a sequence: [2, 4, 6]

 

In de bovenstaande implementatie hebben we eerst de generieke functie ontwikkeld display_info() met de @singledisptach decorateur en registreerde vervolgens de implementatie ervan voor int, float, string en list afzonderlijk. De uitvoer toont de werking van display_info() voor afzonderlijke gegevenstypen.

De @classmethod is een decorateur die wordt gebruikt om klassenmethoden binnen de klasse te definiëren. Klassemethoden zijn gebonden aan de klasse en niet aan het object van de klasse. Het belangrijkste onderscheid tussen statische methoden en klassenmethoden ligt in hun interactie met de klassenstaat. Klassenmethoden hebben toegang tot de klassenstatus en kunnen deze wijzigen, terwijl statische methoden geen toegang hebben tot de klassenstatus en onafhankelijk werken.

Voorbeeld:

class Student:
    total_students = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        Student.total_students += 1

    @classmethod
    def increment_total_students(cls):
        cls.total_students += 1
        print(f"Class method called. Total students now: {cls.total_students}")

# Creating instances of the class
student1 = Student(name="Tom", age=20)
student2 = Student(name="Cruise", age=22)

# Calling the class method
Student.increment_total_students()  #Total students now: 3

# Accessing the class variable
print(f"Total students from student 1: {student1.total_students}")
print(f"Total students from student 2: {student2.total_students}")

 

Output:

Class method called. Total students now: 3
Total students from student 1: 3
Total students from student 2: 3

 

In de bovenstaande implementatie is de Student klasse heeft totaal_studenten als klassevariabele. De @classmethod decorateur wordt gebruikt om de increment_total_students() class-methode om de totaal_studenten variabel. Telkens wanneer we een exemplaar van de klasse Student maken, wordt het totale aantal studenten met één verhoogd. We hebben twee exemplaren van de klasse gemaakt en vervolgens de class-methode gebruikt om de totaal_studenten variabel naar 3, wat ook wordt weerspiegeld door de instanties van de klasse.

De @staticmethod decorateur wordt gebruikt om statische methoden binnen een klasse te definiëren. Statische methoden zijn de methoden die kunnen worden aangeroepen zonder een instantie van de klasse te maken. Statische methoden worden vaak gebruikt als ze geen toegang hebben tot objectgerelateerde parameters en meer gerelateerd zijn aan de klasse als geheel.

Voorbeeld:

class MathOperations:
    @staticmethod
    def add(x, y):
        return x + y

    @staticmethod
    def subtract(x, y):
        return x - y

# Using the static methods without creating an instance of the class
sum_result = MathOperations.add(5, 4)
difference_result = MathOperations.subtract(8, 3)

print("Sum:", sum_result)            
print("Difference:", difference_result)

 

Output:

Sum: 9
Difference: 5

 

In de bovenstaande implementatie hebben we gebruikt @staticmethod om een ​​statische methode add() te definiëren voor de klasse “MathOperations”. We hebben de twee cijfers “4” en “5” toegevoegd, wat resulteert in “9” zonder dat er een instantie van de klasse is gemaakt. Trek op dezelfde manier de twee getallen “8” en “3” af om “5” te krijgen. Op deze manier kunnen statische methoden worden gegenereerd om hulpprogrammafuncties uit te voeren waarvoor de status van een instantie niet vereist is. 

De @property decorateur wordt gebruikt om de gettermethoden voor het klasse-attribuut te definiëren. De gettermethoden zijn de methoden die de waarde van een attribuut retourneren. Deze methoden worden gebruikt voor gegevensinkapseling, die specificeert wie toegang heeft tot de details van de klasse of instantie.

Voorbeeld:

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        # Getter method for the radius.
        return self._radius

    @property
    def area(self):
        # Getter method for the area.
        return 3.14 * self._radius**2

# Creating an instance of the Circle class
my_circle = Circle(radius=5)

# Accessing properties using the @property decorator
print("Radius:", my_circle.radius)          
print("Area:", my_circle.area)  

 

Output:

Radius: 5
Area: 78.5

 

In de bovenstaande implementatie heeft de klasse “Cirkel” een attribuut “radius”. We hebben gebruikt @property om de gettermethoden voor zowel de straal als de oppervlakte in te stellen. Het biedt een schone en consistente interface voor de gebruikers van de klasse om toegang te krijgen tot deze attributen. 

In dit artikel worden enkele van de meest veelzijdige en functionele decorateurs belicht die u kunt gebruiken om uw code flexibeler en leesbaarder te maken. Met deze decorateurs kunt u de functionaliteiten van de oorspronkelijke functie uitbreiden om deze overzichtelijker en minder foutgevoelig te maken. Het zijn als magische accenten die ervoor zorgen dat je Python-programma's er netjes uitzien en soepel werken.
 
 

Kanwal Mehreen is een aspirant-softwareontwikkelaar met een grote interesse in datawetenschap en toepassingen van AI in de geneeskunde. Kanwal werd geselecteerd als de Google Generation Scholar 2022 voor de APAC-regio. Kanwal deelt graag technische kennis door artikelen te schrijven over trending topics en heeft een passie voor het verbeteren van de vertegenwoordiging van vrouwen in de technische industrie.

spot_img

Laatste intelligentie

spot_img