Built-in Funktionen in Python – Teil 3

Später lernen

Es gibt einige built-in Funktionen, die man wahrscheinlich zukünftig irgendwann brauchen wird, aber im Moment eben noch nicht.

Es folgen 14 weitere built-in Funktionen, die zwar nützlich sind, aber erst dann gelernt werden sollten, wenn man sie tatsächlich verwendet.

open

Möchten man in Python aus einer Datei lesen oder in eine Datei schreiben, dann braucht man die Funktion open!
Es ist unwahrscheinlich, aber durchaus möglich, dass man nicht direkt mit Dateien arbeitet, in dem Fall benötigt man die open-Funktion nicht.

>>>with open("update.sql", mode='r') as update_script:
... update_sql_list = update_script.readlines()

input

Die input-Funktion fordert den Benutzer zur Eingabe auf, wartet darauf, dass er die Enter-Taste drückt, und gibt dann den eingegebenen Text zurück.

Das Lesen von der Standardeingabe (was die input-Funktion tut) ist eine Möglichkeit, Eingaben in ein Python-Programm zu bekommen, aber es gibt auch viele andere Möglichkeiten! Man kann Befehlszeilenargumente akzeptieren, aus einer Konfigurationsdatei lesen, aus einer Datenbank lesen und vieles mehr.

Solange man keine Eingabe vom Benutzer anfordert, wird man diese Funktion nicht benötigen. Und wenn man schon eine Weile Python-Skripte schreibt und diese Funktion noch nicht kennt, wird man sie vielleicht nie brauchen.

repr

Benötigt man die lesbare Darstellung eines Objekts, braucht man die Funktion repr!

Alle Python-Objekte haben zwei verschiedene Darstellungsformen: str und repr. Bei den meisten Objekten sind die Darstellungen von str und repr identisch:

>>> str(4), repr(4)
('4', '4')
>>> str([]), repr([])
('[]', '[]')

Aber für einige Objekte sind sie verschieden:

>>> str('hello'), repr("hello")
('hello', "'hello'")
>>> from datetime import date
>>> str(date(2020, 1, 1)), repr(date(2020, 1, 1))
('2020-01-01', 'datetime.date(2020, 1, 1)')

Die Zeichenkettendarstellung, die wir in der Python REPL sehen, verwendet repr, während die print-Funktion auf str zurückgreift:

>>> date(2020, 1, 1)
datetime.date(2020, 1, 1)
>>> "hello!"
'hello!'
>>> print(date(2020, 1, 1))
2020-01-01
>>> print("hello!")
hello!

Die Funktion repr wird z.B. beim Logging, beim Exception Handling und der Implementierung von Dunder-Methoden verwendet.

super

Wenn man in Python Klassen erstellt, wird man wahrscheinlich die Funktion super verwenden müssen. Die Funktion super ist so gut wie unverzichtbar, wenn man von einer anderen Python-Klasse erbt (siehe objektorientierte Programmierung).

Viele Python-Benutzer erstellen nur selten Klassen, denn das Erstellen von Klassen ist kein wesentlicher Bestandteil von Python, obwohl viele Arten der Programmierung es erfordern. Zum Beispiel kann man das Web-Framework Django nicht wirklich nutzen, ohne Klassen zu erstellen.

property

Die property-Funktion ist ein Dekorator und ein Deskriptor, sie wird einem wahrscheinlich etwas magisch vorkommen, wenn man sie zum ersten Mal kennenlernt.
Mit diesem Dekorator kann man ein Attribut erstellen, das immer den Rückgabewert eines bestimmten Funktionsaufrufs zu enthalten scheint. Es ist am einfachsten, dies anhand eines Beispiels zu verstehen.

Hier ist eine Klasse, die property verwendet:

class Circle:

    def __init__(self, radius=1):
        self.radius = radius

    @property
    def diameter(self):
        return self.radius * 2

Hier ist ein Zugriff auf das Durchmesser-Attribut für ein Circle-Objekt:

>>> circle = Circle()
>>> circle.diameter
2
>>> circle.radius = 5
>>> circle.diameter
10

Wenn man in Python objektorientiert programmiert, wird man wahrscheinlich irgendwann etwas über property lernen wollen. Im Gegensatz zu anderen objektorientierten Programmiersprachen verwendet man property anstelle von Getter- und Setter-Methoden.

issubclass und isinstance

Die Funktion issubclass prüft, ob eine Klasse eine Unterklasse von einer oder mehreren anderen Klassen ist.

>>> issubclass(int, bool)
False
>>> issubclass(bool, int)
True
>>> issubclass(bool, object)
True

Die Funktion isinstance prüft, ob ein Objekt eine Instanz von einer oder mehreren Klassen ist.

>>> isinstance(True, str)
False
>>> isinstance(True, bool)
True
>>> isinstance(True, int)
True
>>> isinstance(True, object)
True

Man kann isinstance als Delegierung an issubclass betrachten:

>>> issubclass(type(True), str)
False
>>> issubclass(type(True), bool)
True
>>> issubclass(type(True), int)
True
>>> issubclass(type(True), object)
True

Wenn man Operatoren überlädt (z.B. anpasst, was der +-Operator in einer Klasse ausführt), muss man möglicherweise isinstance verwenden, aber im Allgemeinen sollte man versuchen, starke Typüberprüfung in Python zu vermeiden, so dass man diese nicht oft sehen wird.

hasattr, getattr, setattr, und delattr

Muss man mit einem Attribut eines Objekts arbeiten, aber der Attributname ist dynamisch, dann benötigt man hasattr, getattr, setattr und delattr.

Angenommen, wir haben ein Objekt, das wir auf einen bestimmten Wert prüfen wollen:

>>> class Thing: pass
...
>>> thing = Thing()

Mit der Funktion hasattr können wir prüfen, ob das Objekt ein bestimmtes Attribut hat

>>> hasattr(thing, 'x')
False
>>> thing.x = 4
>>> hasattr(thing, 'x')
True

Mit der Funktion getattr können wir den Wert dieses Attributs abrufen (mit einer optionalen Vorgabe, falls das Attribut nicht existiert):

>>> getattr(thing, 'x')
4
>>> getattr(thing, 'x', 0)
4
>>> getattr(thing, 'y', 0)
0

Mit der Funktion setattr kann man den Wert einstellen:

>>> setattr(thing, 'x', 5)
>>> thing.x
5

Und delattr löscht ein Atttribut:

>>> delattr(thing, 'x')
>>> thing.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Thing' object has no attribute 'x'

classmethod und staticmethod

Die classmethod und staticmethod Dekoratoren sind etwas magisch in der gleichen Weise wie der property Dekorator.

Wenn man eine Methode hat, die entweder auf einer Instanz oder einer Klasse aufrufbar sein soll, verwendet man den classmethod Dekorator. Fabrikmethoden (alternative Konstruktoren) sind ein häufiger Anwendungsfall dafür:

class RomanNumeral:

    """A Roman numeral, represented as a string and numerically."""
    def __init__(self, number):
        self.value = number

    @classmethod
    def from_string(cls, string):
        return cls(roman_to_int(string)) # Funktion existiert noch nicht

Es ist etwas schwieriger, eine gute Verwendung für staticmethod zu finden, da man so gut wie immer eine Funktion auf Modulebene anstelle einer statischen Methode verwenden kann.

class RomanNumeral:

    """A Roman numeral, represented as a string and numerically."""
    SYMBOLS = {'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}

    def __init__(self, number):
        self.value = number
    @classmethod
    def from_string(cls, string):
        return cls(cls.roman_to_int(string))

    @staticmethod
    def roman_to_int(numeral):
        total = 0
        for symbol, next_symbol in zip_longest(numeral, numeral[1:]):
            value = RomanNumeral.SYMBOLS[symbol]
            next_value = RomanNumeral.SYMBOLS.get(next_symbol, 0)
            if value < next_value:
                value = -value
            total += value
        return total

Die obige Funktion roman_to_int erfordert keinen Zugriff auf die Instanz oder die Klasse, so dass sie nicht einmal eine @classmethod sein muss. Es gibt keine wirkliche Notwendigkeit, diese Funktion zu einer staticmethod (statt einer classmethod) zu machen: staticmethod ist einfach restriktiver, um zu signalisieren, dass wir nicht auf die Klasse angewiesen sind, in der unsere Funktion lebt.

next

Die next-Funktion gibt das nächste Element in einem Iterator zurück.
Hier eine kurze Zusammenfassung der Iteratoren, auf die man wahrscheinlich stoßen wird:

  • enumerate Objekte 
  • zip Objekte 
  • der Rückgabewert einer reversed-Funktion 
  • Dateien (das, was man von der open-Funktion zurückerhält) 
  • csv.reader Objekte 
  • generator Ausdrücke 
  • generator Funktionen 

Man kann sich next als eine Möglichkeit vorstellen, manuell eine Schleife über einen Iterator auszuführen, um ein einzelnes Element zu erhalten und dann abzubrechen.

>>> numbers = [2, 1, 3, 4, 7, 11]
>>> squares = (n**2 for n in numbers)
>>> next(squares)
4
>>> for n in squares:
... break
...
>>> n
1
>>> next(squares)
9