Einführung in die eingebauten Methodendekoratoren

PythonPythonBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Abschnitt werden einige integrierte Dekoratoren behandelt, die in Verbindung mit Methodendefinitionen verwendet werden.

Vordefinierte Dekoratoren

Es gibt vordefinierte Dekoratoren, die verwendet werden, um spezielle Arten von Methoden in Klassendefinitionen anzugeben.

class Foo:
    def bar(self,a):
     ...

    @staticmethod
    def spam(a):
     ...

    @classmethod
    def grok(cls,a):
     ...

    @property
    def name(self):
     ...

Gehen wir nacheinander durch.

Statische Methoden

@staticmethod wird verwendet, um sogenannte statische Klassenmethoden (aus C++/Java) zu definieren. Eine statische Methode ist eine Funktion, die Teil der Klasse ist, aber auf Instanzen nicht operiert.

class Foo(object):
    @staticmethod
    def bar(x):
        print('x =', x)

>>> Foo.bar(2) ## x=2
>>>

Statische Methoden werden manchmal verwendet, um internen Unterstützungs-Code für eine Klasse zu implementieren. Beispielsweise Code, um die erstellten Instanzen zu verwalten (Speicherverwaltung, Systemressourcen, Persistenz, Sperren usw.). Sie werden auch von bestimmten Designmustern verwendet (hier nicht behandelt).

Klassenmethoden

@classmethod wird verwendet, um Klassenmethoden zu definieren. Eine Klassenmethode ist eine Methode, die das Klass -Objekt als erstes Argument statt der Instanz erhält.

class Foo:
    def bar(self):
        print(self)
    @classmethod
    def spam(cls):
        print(cls)

>>> f = Foo()
>>> f.bar()
<__main__.Foo object at 0x971690>   ## Die Instanz `f`
>>> Foo.spam()
<class '__main__.Foo'>              ## Die Klasse `Foo`
>>>

Klassenmethoden werden am häufigsten als Werkzeug zur Definition alternativer Konstruktoren verwendet.

class Date:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
    @classmethod
    def today(cls):
        ## Beachten Sie, wie die Klasse als Argument übergeben wird
        tm = time.localtime()
        ## Und verwendet wird, um eine neue Instanz zu erstellen
        return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)

d = Date.today()

Klassenmethoden lösen einige knifflige Probleme mit Funktionen wie Vererbung.

class Date:
 ...
    @classmethod
    def today(cls):
        ## Holt die richtige Klasse (z.B. `NewDate`)
        tm = time.localtime()
        return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)

class NewDate(Date):
 ...

d = NewDate.today()

Übung 7.11: Praxis der Klassenmethoden

In Ihren Dateien report.py und portfolio.py ist die Erstellung eines Portfolio -Objekts etwas verwirrt. Beispielsweise hat das report.py -Programm Code wie diesen:

def read_portfolio(filename, **opts):
    '''
    Liest eine Datei mit einem Aktienportfolio in eine Liste von Wörterbüchern mit den Schlüsseln
    name, shares und price ein.
    '''
    with open(filename) as lines:
        portdicts = fileparse.parse_csv(lines,
                                        select=['name','shares','price'],
                                        types=[str,int,float],
                                        **opts)

    portfolio = [ Stock(**d) for d in portdicts ]
    return Portfolio(portfolio)

und die portfolio.py -Datei definiert Portfolio() mit einem eigenartigen Initialisierer wie diesem:

class Portfolio:
    def __init__(self, holdings):
        self._holdings = holdings
  ...

Ehrlich gesagt ist die Verantwortungsabfolge ein bisschen verwirrend, weil der Code verteilt ist. Wenn eine Portfolio -Klasse eine Liste von Stock -Instanzen enthalten soll, sollten Sie vielleicht die Klasse etwas klarer gestalten. So:

## portfolio.py

import stock

class Portfolio:
    def __init__(self):
        self._holdings = []

    def append(self, holding):
        if not isinstance(holding, stock.Stock):
            raise TypeError('Expected a Stock instance')
        self._holdings.append(holding)
  ...

Wenn Sie ein Portfolio aus einer CSV -Datei lesen möchten, sollten Sie vielleicht eine Klassenmethode dafür erstellen:

## portfolio.py

import fileparse
import stock

class Portfolio:
    def __init__(self):
        self._holdings = []

    def append(self, holding):
        if not isinstance(holding, stock.Stock):
            raise TypeError('Expected a Stock instance')
        self._holdings.append(holding)

    @classmethod
    def from_csv(cls, lines, **opts):
        self = cls()
        portdicts = fileparse.parse_csv(lines,
                                        select=['name','shares','price'],
                                        types=[str,int,float],
                                        **opts)

        for d in portdicts:
            self.append(stock.Stock(**d))

        return self

Um diese neue Portfolio -Klasse zu verwenden, können Sie jetzt Code wie diesen schreiben:

>>> from portfolio import Portfolio
>>> with open('portfolio.csv') as lines:
...     port = Portfolio.from_csv(lines)
...
>>>

Machen Sie diese Änderungen an der Portfolio -Klasse und ändern Sie den report.py -Code, um die Klassenmethode zu verwenden.

✨ Lösung prüfen und üben

Zusammenfassung

Herzlichen Glückwunsch! Sie haben das Lab zu Dekorierten Methoden abgeschlossen. Sie können in LabEx weitere Labs ausprobieren, um Ihre Fähigkeiten zu verbessern.