Attributzugriff und gebundene Methoden

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 Lab lernen Sie etwas über den Zugriff auf Attribute in Python. Sie werden untersuchen, wie Sie Funktionen wie getattr() und setattr() verwenden können, um Objektattribute effektiv zu manipulieren.

Zusätzlich werden Sie mit gebundenen Methoden experimentieren. Das Lab wird Sie durch diese Konzepte führen, und Sie werden während des Prozesses eine Datei namens tableformat.py erstellen.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/PythonStandardLibraryGroup(["Python Standard Library"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ModulesandPackagesGroup(["Modules and Packages"]) python(("Python")) -.-> python/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/build_in_functions("Build-in Functions") python/ModulesandPackagesGroup -.-> python/using_packages("Using Packages") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") python/PythonStandardLibraryGroup -.-> python/data_collections("Data Collections") subgraph Lab Skills python/function_definition -.-> lab-132491{{"Attributzugriff und gebundene Methoden"}} python/build_in_functions -.-> lab-132491{{"Attributzugriff und gebundene Methoden"}} python/using_packages -.-> lab-132491{{"Attributzugriff und gebundene Methoden"}} python/classes_objects -.-> lab-132491{{"Attributzugriff und gebundene Methoden"}} python/data_collections -.-> lab-132491{{"Attributzugriff und gebundene Methoden"}} end

Das Verständnis des Attributzugriffs in Python

In Python sind Objekte ein grundlegendes Konzept. Sie können Daten in Attributen speichern, die wie benannte Container für Werte sind. Sie können sich Attribute als Variablen vorstellen, die zu einem Objekt gehören. Es gibt mehrere Möglichkeiten, auf diese Attribute zuzugreifen. Die einfachste und am häufigsten verwendete Methode ist die Punktnotation (.). Python bietet jedoch auch spezifische Funktionen, die Ihnen mehr Flexibilität beim Umgang mit Attributen geben.

Die Punktnotation

Beginnen wir damit, ein Stock-Objekt zu erstellen und zu sehen, wie wir seine Attribute mithilfe der Punktnotation manipulieren können. Die Punktnotation ist eine einfache und intuitive Möglichkeit, auf die Attribute eines Objekts zuzugreifen und sie zu ändern.

Öffnen Sie zunächst ein neues Terminal und starten Sie die Python interaktive Shell. Hier können Sie Python-Code Zeile für Zeile schreiben und ausführen.

## Open a new terminal and run Python interactive shell
python3

## Import the Stock class from the stock module
from stock import Stock

## Create a Stock object
s = Stock('GOOG', 100, 490.1)

## Get an attribute
print(s.name)    ## Output: 'GOOG'

## Set an attribute
s.shares = 50
print(s.shares)  ## Output: 50

## Delete an attribute
del s.shares
## If we try to access s.shares now, we'll get an AttributeError

Im obigen Code importieren wir zunächst die Stock-Klasse aus dem stock-Modul. Dann erstellen wir eine Instanz der Stock-Klasse namens s. Um den Wert des name-Attributs zu erhalten, verwenden wir s.name. Um den Wert des shares-Attributs zu ändern, weisen wir einfach einen neuen Wert zu s.shares zu. Und wenn wir ein Attribut entfernen möchten, verwenden wir das del-Schlüsselwort, gefolgt vom Attributnamen.

Funktionen für den Attributzugriff

Python bietet vier eingebaute Funktionen, die sehr nützlich für die Attributmanipulation sind. Diese Funktionen geben Ihnen mehr Kontrolle beim Umgang mit Attributen, insbesondere wenn Sie sie dynamisch behandeln müssen.

  1. getattr() – Diese Funktion wird verwendet, um den Wert eines Attributs zu erhalten.
  2. setattr() – Sie können damit den Wert eines Attributs festlegen.
  3. delattr() – Mit dieser Funktion können Sie ein Attribut löschen.
  4. hasattr() – Diese Funktion prüft, ob ein Attribut in einem Objekt existiert.

Sehen wir uns an, wie man diese Funktionen verwendet:

## Create a new Stock object
s = Stock('GOOG', 100, 490.1)

## Get an attribute
print(getattr(s, 'name'))       ## Output: 'GOOG'

## Set an attribute
setattr(s, 'shares', 50)
print(s.shares)                 ## Output: 50

## Check if an attribute exists
print(hasattr(s, 'name'))       ## Output: True
print(hasattr(s, 'symbol'))     ## Output: False

## Delete an attribute
delattr(s, 'shares')
print(hasattr(s, 'shares'))     ## Output: False

Diese Funktionen sind besonders nützlich, wenn Sie dynamisch mit Attributen arbeiten müssen. Anstatt hartcodierte Attributnamen zu verwenden, können Sie Variablennamen nutzen. Wenn Sie beispielsweise eine Variable haben, die den Namen eines Attributs speichert, können Sie diese Variable an diese Funktionen übergeben, um Operationen auf dem entsprechenden Attribut auszuführen. Dies gibt Ihnen mehr Flexibilität in Ihrem Code, insbesondere wenn Sie auf dynamische Weise mit verschiedenen Objekten und Attributen umgehen.

Die Verwendung von getattr() für die generische Objektverarbeitung

Die getattr()-Funktion ist ein leistungsstarkes Werkzeug in Python, das es Ihnen ermöglicht, auf die Attribute eines Objekts auf dynamische Weise zuzugreifen. Dies ist besonders nützlich, wenn Sie Objekte auf eine generische Weise verarbeiten möchten. Anstatt Code zu schreiben, der für einen bestimmten Objekttyp spezifisch ist, können Sie getattr() verwenden, um mit jedem Objekt zu arbeiten, das die erforderlichen Attribute hat. Diese Flexibilität macht Ihren Code wiederverwendbarer und anpassungsfähiger.

Die Verarbeitung mehrerer Attribute

Beginnen wir damit, zu lernen, wie man mithilfe der getattr()-Funktion auf mehrere Attribute eines Objekts zugreift. Dies ist ein häufiges Szenario, wenn Sie bestimmte Informationen aus einem Objekt extrahieren müssen.

Öffnen Sie zunächst die Python interaktive Shell, wenn Sie die vorherige geschlossen haben. Sie können dies tun, indem Sie den folgenden Befehl in Ihrem Terminal ausführen:

## Open a Python interactive shell if you closed the previous one
python3

Als Nächstes werden wir die Stock-Klasse importieren und ein Stock-Objekt erstellen. Die Stock-Klasse repräsentiert eine Aktie mit Attributen wie name, shares und price.

## Import the Stock class and create a stock object
from stock import Stock
s = Stock('GOOG', 100, 490.1)

Jetzt definieren wir eine Liste von Attributnamen, auf die wir zugreifen möchten. Diese Liste wird uns helfen, über die Attribute zu iterieren und ihre Werte auszugeben.

## Define a list of attribute names
fields = ['name', 'shares', 'price']

Schließlich verwenden wir eine for-Schleife, um über die Liste der Attributnamen zu iterieren und auf jedes Attribut mithilfe von getattr() zuzugreifen. Wir geben für jede Iteration den Attributnamen und seinen Wert aus.

## Access each attribute using getattr()
for name in fields:
    print(f"{name}: {getattr(s, 'name')}" if name == 'name' else f"{name}: {getattr(s, name)}")

Wenn Sie diesen Code ausführen, sehen Sie die folgende Ausgabe:

name: GOOG
shares: 100
price: 490.1

Diese Ausgabe zeigt, dass wir in der Lage waren, die Werte mehrerer Attribute des Stock-Objekts mithilfe der getattr()-Funktion zuzugreifen und auszugeben.

Standardwerte mit getattr()

Die getattr()-Funktion bietet auch ein nützliches Feature: die Möglichkeit, einen Standardwert anzugeben, wenn das Attribut, auf das Sie zugreifen möchten, nicht existiert. Dies kann verhindern, dass Ihr Code einen AttributeError auslöst und ihn robuster machen.

Sehen wir uns an, wie dies funktioniert. Zunächst versuchen wir, auf ein Attribut zuzugreifen, das im Stock-Objekt nicht existiert. Wir verwenden getattr() und geben einen Standardwert von 'N/A' an.

## Try to access an attribute that doesn't exist
print(getattr(s, 'symbol', 'N/A'))  ## Output: 'N/A'

In diesem Fall, da das symbol-Attribut im Stock-Objekt nicht existiert, gibt getattr() den Standardwert 'N/A' zurück.

Jetzt vergleichen wir dies mit dem Zugriff auf ein vorhandenes Attribut. Wir greifen auf das name-Attribut zu, das im Stock-Objekt existiert.

## Compare with an existing attribute
print(getattr(s, 'name', 'N/A'))    ## Output: 'GOOG'

Hier gibt getattr() den tatsächlichen Wert des name-Attributs zurück, der 'GOOG' ist.

Die Verarbeitung einer Sammlung von Objekten

Die getattr()-Funktion wird noch leistungsstärker, wenn Sie eine Sammlung von Objekten verarbeiten müssen. Sehen wir uns an, wie wir sie verwenden können, um ein Portfolio von Aktien zu verarbeiten.

Zunächst importieren wir die read_portfolio-Funktion aus dem stock-Modul. Diese Funktion liest ein Portfolio von Aktien aus einer CSV-Datei und gibt eine Liste von Stock-Objekten zurück.

## Import the portfolio reading function
from stock import read_portfolio

Als Nächstes verwenden wir die read_portfolio-Funktion, um das Portfolio aus einer CSV-Datei namens portfolio.csv zu lesen.

## Read the portfolio from CSV file
portfolio = read_portfolio('portfolio.csv')

Schließlich verwenden wir eine for-Schleife, um über die Liste der Stock-Objekte im Portfolio zu iterieren. Für jede Aktie verwenden wir getattr(), um auf die name- und shares-Attribute zuzugreifen und ihre Werte auszugeben.

## Print the name and shares of each stock
for stock in portfolio:
    print(f"Stock: {getattr(stock, 'name')}, Shares: {getattr(stock, 'shares')}")

Dieser Ansatz macht Ihren Code flexibler, da Sie mit Attributnamen als Strings arbeiten können. Diese Strings können als Argumente übergeben oder in Datenstrukturen gespeichert werden, sodass Sie die Attribute, auf die Sie zugreifen möchten, leicht ändern können, ohne die Kernlogik Ihres Codes zu ändern.

Das Erstellen eines Tabellenformatierers mithilfe des Attributzugriffs

In der Programmierung ist der Attributzugriff ein grundlegendes Konzept, das es uns ermöglicht, mit den Eigenschaften von Objekten zu interagieren. Jetzt werden wir das, was wir über den Attributzugriff gelernt haben, in die Praxis umsetzen. Wir werden ein nützliches Werkzeug erstellen: einen Tabellenformatierer. Dieser Formatierer nimmt eine Sammlung von Objekten und zeigt sie in tabellarischer Form an, wodurch die Daten leichter lesbar und verständlich werden.

Das Erstellen des tableformat.py-Moduls

Zunächst müssen wir eine neue Python-Datei erstellen. Diese Datei wird den Code für unseren Tabellenformatierer enthalten.

Um die Datei zu erstellen, folgen Sie diesen Schritten:

  1. Klicken Sie im WebIDE auf das Menü "File".
  2. Wählen Sie aus der Dropdown-Liste "New File" aus.
  3. Speichern Sie die neu erstellte Datei als tableformat.py im Verzeichnis /home/labex/project/.

Jetzt, da wir unsere Datei haben, schreiben wir den Code für die print_table()-Funktion in tableformat.py. Diese Funktion wird für die Formatierung und Ausgabe unserer Objekte in einer Tabelle verantwortlich sein.

def print_table(objects, fields):
    """
    Print a collection of objects as a formatted table.

    Args:
        objects: A sequence of objects
        fields: A list of attribute names
    """
    ## Print the header
    headers = fields
    for header in headers:
        print(f"{header:>10}", end=' ')
    print()

    ## Print the separator line
    for header in headers:
        print("-" * 10, end=' ')
    print()

    ## Print the data
    for obj in objects:
        for field in fields:
            value = getattr(obj, field)
            print(f"{value:>10}", end=' ')
        print()

Lassen Sie uns analysieren, was diese Funktion tut:

  1. Sie nimmt zwei Argumente entgegen: eine Sequenz von Objekten und eine Liste von Attributnamen. Die Sequenz von Objekten ist die Daten, die wir anzeigen möchten, und die Liste von Attributnamen sagt der Funktion, welche Eigenschaften der Objekte angezeigt werden sollen.
  2. Sie gibt eine Kopfzeile aus. Die Kopfzeile enthält die Namen der Attribute, an denen wir interessiert sind.
  3. Sie gibt eine Trennlinie aus. Diese Linie hilft, den Kopf von den Daten visuell zu trennen.
  4. Für jedes Objekt in der Sequenz gibt sie den Wert jedes angegebenen Attributs aus. Sie verwendet die getattr()-Funktion, um auf den Attributwert jedes Objekts zuzugreifen.

Jetzt testen wir unsere print_table()-Funktion, um zu sehen, ob sie wie erwartet funktioniert.

## Open a Python interactive shell
python3

## Import our modules
from stock import read_portfolio
import tableformat

## Read the portfolio data
portfolio = read_portfolio('portfolio.csv')

## Print the portfolio as a table with name, shares, and price columns
tableformat.print_table(portfolio, ['name', 'shares', 'price'])

Wenn Sie den obigen Code ausführen, sollten Sie die folgende Ausgabe sehen:

      name     shares      price
---------- ---------- ----------
        AA        100       32.2
       IBM         50       91.1
       CAT        150      83.44
      MSFT        200      51.23
        GE         95      40.37
      MSFT         50       65.1
       IBM        100      70.44

Einer der großen Vorteile unserer print_table()-Funktion ist ihre Flexibilität. Wir können die angezeigten Spalten einfach ändern, indem wir die fields-Liste ändern.

## Just show shares and name
tableformat.print_table(portfolio, ['shares', 'name'])

Das Ausführen dieses Codes gibt Ihnen die folgende Ausgabe:

    shares       name
---------- ----------
       100         AA
        50        IBM
       150        CAT
       200       MSFT
        95         GE
        50       MSFT
       100        IBM

Die Stärke dieses Ansatzes liegt in seiner Allgemeingültigkeit. Wir können die gleiche print_table()-Funktion verwenden, um Tabellen für jeden Objekttyp auszugeben, solange wir die Namen der Attribute kennen, die wir anzeigen möchten. Dies macht unseren Tabellenformatierer zu einem sehr nützlichen Werkzeug in unserem Programmierwerkzeugkasten.

✨ Lösung prüfen und üben

Das Verständnis von gebundenen Methoden in Python

In Python sind Methoden ein spezieller Typ von Attributen, die Sie aufrufen können. Wenn Sie eine Methode über ein Objekt zugreifen, erhalten Sie was wir eine "gebundene Methode" nennen. Eine gebundene Methode ist im Wesentlichen eine Methode, die an ein bestimmtes Objekt gebunden ist. Das bedeutet, dass sie auf die Daten des Objekts zugreifen und damit arbeiten kann.

Der Zugriff auf Methoden als Attribute

Beginnen wir mit der Erkundung von gebundenen Methoden anhand unserer Stock-Klasse. Zunächst sehen wir uns an, wie man eine Methode als Attribut eines Objekts zugreift.

## Open a Python interactive shell
python3

## Import the Stock class and create a stock object
from stock import Stock
s = Stock('GOOG', 100, 490.10)

## Access the cost method without calling it
cost_method = s.cost
print(cost_method)  ## Output: <bound method Stock.cost of <stock.Stock object at 0x...>>

## Call the method
result = cost_method()
print(result)  ## Output: 49010.0

## You can also do this in one step
print(s.cost())  ## Output: 49010.0

Im obigen Code importieren wir zunächst die Stock-Klasse und erstellen eine Instanz davon. Dann greifen wir auf die cost-Methode des s-Objekts zu, ohne sie tatsächlich aufzurufen. Dadurch erhalten wir eine gebundene Methode. Wenn wir diese gebundene Methode aufrufen, berechnet sie die Kosten basierend auf den Daten des Objekts. Sie können die Methode auch direkt in einem Schritt auf dem Objekt aufrufen.

Die Verwendung von getattr() mit Methoden

Eine andere Möglichkeit, auf Methoden zuzugreifen, ist die Verwendung der getattr()-Funktion. Diese Funktion ermöglicht es Ihnen, ein Attribut eines Objekts anhand seines Namens zu erhalten.

## Get the cost method using getattr
cost_method = getattr(s, 'cost')
print(cost_method)  ## Output: <bound method Stock.cost of <stock.Stock object at 0x...>>

## Call the method
result = cost_method()
print(result)  ## Output: 49010.0

## Get and call in one step
result = getattr(s, 'cost')()
print(result)  ## Output: 49010.0

Hier verwenden wir getattr(), um die cost-Methode aus dem s-Objekt zu erhalten. Wie zuvor können wir die gebundene Methode aufrufen, um das Ergebnis zu erhalten. Und Sie können die Methode sogar in einer einzigen Zeile erhalten und aufrufen.

Die gebundene Methode und ihr Objekt

Eine gebundene Methode behält immer einen Verweis auf das Objekt, von dem aus sie zugegriffen wurde. Das bedeutet, dass auch wenn Sie die Methode in einer Variablen speichern, sie noch weiß, zu welchem Objekt sie gehört und auf die Daten des Objekts zugreifen kann.

## Store the cost method in a variable
c = s.cost

## Call the method
print(c())  ## Output: 49010.0

## Change the object's state
s.shares = 75

## Call the method again - it sees the updated state
print(c())  ## Output: 36757.5

In diesem Beispiel speichern wir die cost-Methode in einer Variablen c. Wenn wir c() aufrufen, berechnet es die Kosten basierend auf den aktuellen Daten des Objekts. Dann ändern wir das shares-Attribut des s-Objekts. Wenn wir c() erneut aufrufen, verwendet es die aktualisierten Daten, um die neuen Kosten zu berechnen.

Die Erkundung der internen Struktur der gebundenen Methode

Eine gebundene Methode hat zwei wichtige Attribute, die uns mehr Informationen über sie geben.

  • __self__: Dieses Attribut verweist auf das Objekt, an das die Methode gebunden ist.
  • __func__: Dieses Attribut ist das eigentliche Funktionsobjekt, das die Methode repräsentiert.
## Get the cost method
c = s.cost

## Examine the bound method attributes
print(c.__self__)  ## Output: <stock.Stock object at 0x...>
print(c.__func__)  ## Output: <function Stock.cost at 0x...>

## You can manually call the function with the object
print(c.__func__(c.__self__))  ## Output: 36757.5 (same as c())

Hier greifen wir auf die __self__- und __func__-Attribute der gebundenen Methode c zu. Wir können sehen, dass __self__ das s-Objekt ist und __func__ die cost-Funktion. Wir können die Funktion sogar manuell aufrufen, indem wir das Objekt als Argument übergeben, und es gibt uns dasselbe Ergebnis wie der direkte Aufruf der gebundenen Methode.

Ein Beispiel mit einer Methode, die Argumente nimmt

Sehen wir uns an, wie gebundene Methoden mit einer Methode funktionieren, die Argumente nimmt, wie die sell()-Methode.

## Get the sell method
sell_method = s.sell

## Examine the method
print(sell_method)  ## Output: <bound method Stock.sell of <stock.Stock object at 0x...>>

## Call the method with an argument
sell_method(25)
print(s.shares)  ## Output: 50

## Call the method manually using __func__ and __self__
sell_method.__func__(sell_method.__self__, 10)
print(s.shares)  ## Output: 40

In diesem Beispiel erhalten wir die sell-Methode als gebundene Methode. Wenn wir sie mit einem Argument aufrufen, aktualisiert sie das shares-Attribut des s-Objekts. Wir können die Methode auch manuell unter Verwendung der __func__- und __self__-Attribute aufrufen und dabei auch das Argument übergeben.

Das Verständnis von gebundenen Methoden hilft Ihnen zu verstehen, wie Python's Objektsystem unter der Haube funktioniert, was für das Debugging, die Metaprogrammierung und das Erstellen fortschrittlicher Programmiermuster nützlich sein kann.

Zusammenfassung

In diesem Lab haben Sie sich mit Python's Attributzugriffssystem und seinen zugrunde liegenden Mechanismen vertraut gemacht. Sie wissen nun, wie Sie auf Objektattribute mithilfe der Punktnotation und Funktionen wie getattr(), setattr(), delattr() und hasattr() zugreifen können. Darüber hinaus verstehen Sie, wie Sie getattr() für eine generische und flexible Objektverarbeitung nutzen können und wie Sie einen Tabellenformatierer für jede Sammlung von Objekten erstellen können.

Sie haben auch das Konzept der gebundenen Methoden und wie diese eine Verbindung zu ihren Objekten aufrechterhalten, erfasst. Diese grundlegenden Konzepte sind von entscheidender Bedeutung für fortgeschrittene Python-Programmiertechniken wie Introspektion, Reflektion und Metaprogrammierung. Das Verständnis des Attributzugriffs ermöglicht es Ihnen, flexibleres und leistungsfähigeres Code zu schreiben, das verschiedene Objekttypen verarbeiten kann.