Checks

Variablen und Ausdrücke

  • Erstellt in der Python-Shell einige Variablen. Was passiert, wenn ihr Leerzeichen, Bindestriche oder andere Zeichen in den Variablennamen einfügt?

    >>> x = 3
    >>> var fünf = 5
      File "<stdin>", line 1
        var fünf = 5
            ^^^^
    SyntaxError: invalid syntax
    >>> var_fünf = 5
    
  • Ändern sich die Ergebnisse, wenn ihr Klammern verwendet, um Zahlen auf verschiedene Weise zu gruppieren?

    >>> 2 + 3 * 4 - 5 / 6
    13.166666666666666
    >>> (2 + 3) * 4 - 5 / 6
    19.166666666666668
    >>> 2 + (3 * 4) - 5 / 6
    13.166666666666666
    >>> 2 + 3 * (4 - 5) / 6
    1.5
    
  • Welche der folgenden Variablen- und Funktionsnamen sind eurer Meinung nach kein guter Python-Stil, und warum?

    var*

    ❌ enthält ein unzulässiges Zeichen (*)

    varname

    ✅ ok, aber mit Unterstich einfacher lesbar

    func_name()

    varName

    ❌ Gemischte Groß- und Kleinschreibung

    VARNAME

    ❌ Nur Großbuchstaben, schlecht lesbar

    very_very_long_var_name

    ✅ ok, aber sehr lang und daher nur zu empfehlen, wenn zwischen vielen sehr ähnlichen Variablen unterschieden werden soll

Zahlen

  • Erstellt einige Zahlenvariablen (Ganzzahlen, Gleitkommazahlen und komplexe Zahlen). Experimentiert ein wenig damit, was passiert, wenn ihr Operationen mit ihnen durchführt, auch Typ-übergreifend.

    >>> x = 3
    >>> import math
    >>> pi = math.pi
    >>> pi
    3.141592653589793
    >>> c = 3j4
      File "<stdin>", line 1
        c = 3j4
             ^
    SyntaxError: invalid imaginary literal
    >>> c = 3 +4j
    >>> c
    (3+4j)
    >>> x * c
    (9+12j)
    >>> x + c
    (6+4j)
    

Komplexe Zahlen

  • Ladet das Modul math und probiert einige der Funktionen aus. Ladet dann auch das Modul cmath und macht dasselbe.

    >>> from math import sqrt
    >>> sqrt(3)
    1.7320508075688772
    >>> from cmath import sqrt
    >>> sqrt(3)
    (1.7320508075688772+0j)
    
  • Wie könnt ihr die Funktionen des math-Moduls wiederherstellen?

    >>> from math import sqrt
    >>> sqrt(3)
    1.7320508075688772
    

Boolesche Werte

  • Entscheidet, ob die folgenden Aussagen wahr oder falsch sind:

    • 1 → True

    • 0 → False

    • -1 → True

    • [0] → True (Liste mit einem Item)

    • 1 and 0 → False

    • 1 > 0 or [] → True

Listen

  • Was gibt len() für jeden der folgenden Fälle zurück:

    >>> len([3])
    1
    >>> len([])
    0
    >>> len([[1, [2, 3], 4], "5 6"])
    2
    
  • Wie würdet ihr mit len() und Slices die zweite Hälfte einer Liste ermitteln, wenn ihr nicht wisst, wie groß sie ist?

    >>> l = [[1, [2, 3], 4], "5 6"]
    >>> l[len(l) // 2 :]
    ['5 6']
    
  • Wie könntet ihr die letzten zwei Einträge einer Liste an den Anfang verschieben, ohne die Reihenfolge der beiden zu ändern?

    >>> l[-2:] + l[:2]
    ['5 6', 7, [1, [2, 3], 4], '5 6']
    
  • Welcher der folgenden Fälle löst eine Exception aus?

    • min(["1", "2", "3"])

    • max([1, 2, "3"])

    • [1,2,3].count("1")

    max([1, 2, "3"]), da Strings und Ganzzahlen nicht verglichen werden können; daher ist es unmöglich, einen Maximalwert zu erhalten.

  • Wenn ihr eine Liste l habt, wie könnt ihr daraus einen bestimmten Wert i entfernen?

    >>> if i in l:
    ...     l.remove(i)
    ...
    

    Bemerkung

    Mit diesem Code wird nur das erste Vorkommen von i entfernt. Um alle Vorkommen von i aus der Liste zu entfernen, könnte die Liste z.B. in den Set-Typ umgewandelt werden:

    >>> l = set(l)
    >>> if i in l:
    ...     l.remove(i)
    ...
    >>> l = list(l)
    

    Dies ändert jedoch auch die Reihenfolge der Elemente.

  • Wenn ihr eine verschachtelte Liste ll habt, wie könnt ihr eine Kopie nll dieser Liste erhalten, in der ihr die Elemente ändern könnt, ohne den Inhalt von ll zu verändern?

    >>> import copy
    >>> nll = copy.deepcopy(ll)
    
  • Stellt sicher, dass das Objekt my_collection eine Liste ist, bevor ihr versucht, daran Daten anzuhängen.

    >>> my_collection = []
    >>> if isinstance(my_collection, list):
    ...     print(f"my_collection is a list")
    ...
    my_collection is a list
    
  • Welche anderen Optionen könntet ihr neben der expliziten Überprüfung des Typs haben?

Tupel

  • Erläutert, warum die folgenden Operationen nicht auf das Tuple t angewendet werden können:

    • t.append(1)

    • t[2] = 2

    • del t[3]

    Alle Operation versuchen, das Tuple t zu ändern. Tuples können jedoch nicht verändert werden.

  • Wie könnt ihr die Elemente eines Tuple sortieren?

    >>> sorted(t)
    

Sets

  • Wieviele Elemente hat ein Set, wenn es aus der folgenden Liste [4, 2, 3, 2, 1] gebildet wird?

    Vier unterschiedliche Elemente.

Dictionaries

  • Angenommen, ihr habt die beiden Dictionaries x = {"a":1, "b":2, "c":3, "d":4} und y = {"a":5, "e":6, "f":7}. Was wäre der Inhalt von x, nachdem die folgenden Codeschnipsel ausgeführt wurden?

    >>> del x["b"]
    >>> z = x.setdefault("e", 8)
    >>> x.update(y)
    
    >>> x = {"a": 1, "b": 2, "c": 3, "d": 4}
    >>> y = {"a": 5, "e": 6, "f": 7}
    >>> del x["b"]
    >>> z = x.setdefault("e", 8)
    >>> x.update(y)
    >>> x
    {'a': 5, 'c': 3, 'd': 4, 'e': 6, 'f': 7}
    
  • Welcher der folgenden Ausdrücke kann ein Schlüssel eines Dictionary sein: 1; "Veit"; ("Veit", [1]); [("Veit", [1])]; ["Veit"]; ("Veit", "Tim", "Monique")

    >>> d = {}
    >>> d[1] = None
    >>> d["Veit"] = None
    >>> d[("Veit", [1])]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    >>> d[["Veit"]] = None
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    >>> d[("Veit", "Tim", "Monique")] = None
    
  • Ihr könnt ein Dictionary verwenden, und das wie ein Tabelle einer Tabellenkalkulation verwenden, indem ihr Tupel als Schlüssel Zeilen- und Spaltenwerte verwendet. Schreibt Beispielcode, um Werte hinzuzufügen und wieder abzufragen.

    >>> sheet = {}
    >>> sheet[("A", 0)] = 1
    >>> sheet[("A", 1)] = 2
    >>> sheet[("B", 0)] = 3
    >>> sheet[("B", 1)] = 4
    >>> print(sheet[("A", 1)])
    2
    
  • Wie könnt ihr alle Dubletten aus einer Liste entfernen ohne die Reihenfolge der Elemente in der Liste zu ändern?

    Hierfür können die Schlüssel eines Dictionaries verwendet werden:

    >>> list(dict.fromkeys(l))
    

Zeichenketten

  • Könnt ihr z.B. eine Zeichenkette mit einer ganzen Zahl addieren oder multiplizieren, oder mit einer Gleitkommazahl oder einer komplexen Zahl?

    >>> x = 3
    >>> c = 3 + 4j
    >>> snake = "🐍"
    >>> x + snake
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'int' and 'str'
    >>> x * snake
    '🐍🐍🐍'
    >>> c + snake
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'complex' and 'str'
    >>> c * snake
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: can't multiply sequence by non-int of type 'complex'
    

Operatoren und Funktionen

  • Welche der folgenden Zeichenketten können nicht in Zahlen umgewandelt werden und warum?

    >>> int("1e2")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: invalid literal for int() with base 10: '1e2'
    >>> int(1e+2)
    100
    >>> int("1+2")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: invalid literal for int() with base 10: '1+2'
    >>> int("+2")
    2
    

string

  • Wie könnt ihr eine Überschrift wie variables and expressions so abändern, dass sie statt Leerzeichen Bindestriche enthält und so besser als Dateinamen verwendet werden kann?

    >>> ve = "variables and expressions"
    >>> "-".join(ve.split())
    'variables-and-expressions'
    
  • Wenn ihr überprüfen wollt, ob eine Zeile mit .. note:: beginnt, welche Methode würdet ihr verwenden? Gibt es auch noch andere Möglichkeiten?

    >>> x.startswith(".. note::")
    True
    >>> x[:9] == ".. note::"
    True
    
  • Angenommen, ihr habt eine Zeichenkette mit Ausrufezeichen, Anführungszeichen und Zeilenumbruch. Wie können diese aus der Zeichenkette entfernt werden?

    >>> hipy = "„Hello Pythonistas!“\n"
    >>> hipy.strip("„“!\n")
    'Hello Pythonistas'
    
  • Wie könnt ihr alle Leerräume und Satzzeichen aus einer Zeichenfolge in einen Bindestrich (-) ändern?

    >>> from string import punctuation, whitespace
    >>> chars = punctuation + whitespace
    >>> subs = str.maketrans(chars, len(chars) * "-")
    >>> hipy = "Hello Pythonistas!\n"
    >>> hipy.translate(subs)
    'Hello-Pythonistas--'
    

re

  • Welchen regulären Ausdruck würdet ihr verwenden, um Zeichenfolgen zu finden, die die Zahlen zwischen -3 und +3 darstellen?

    r"-?[0-3]" oder r"-{0,1}[0-3]"

    ?

    ist ein Quantifizierer für ein oder kein Vorkommen.

  • Welchen regulären Ausdruck würdet ihr verwenden, um Hexadezimalwerte zu finden?

    r"0[xX][0-9a-fA-F]+"

    entspricht einem Ausdruck, der mit 0 beginnt, gefolgt von einem kleinen oder großen x, gefolgt von einem oder mehreren Zeichen in den Bereichen 0-9, a-f oder A-F.

input()

  • Wie könnt ihr mit der input()-Funktion String- und Integer-Werte erhalten?

    >>> year_birth = input("Geburtsjahr: ")
    Geburtsjahr: 1964
    >>> type(year_birth)
    <class 'str'>
    >>> year_birth = int(input("Geburtsjahr: "))
    Geburtsjahr: 1964
    >>> type(year_birth)
    <class 'int'>
    
  • Wie wirkt es sich aus, wenn ihr int() nicht verwendet um den Aufruf von input() für Integer-Eingaben zu verwenden?

    >>> import datetime
    >>> current = datetime.datetime.now()
    >>> year = current.year
    >>> year_birth = input("Geburtsjahr? ")
    Geburtsjahr? 1964
    >>> age = year - year_birth
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for -: 'int' and 'str'
    
  • Könnt ihr den Code so abändern, dass er eine Fließkommazahl akzeptiert?

    >>> import datetime
    >>> current = datetime.datetime.now()
    >>> year = current.year
    >>> year_birth = float(input("Geburtsjahr: "))
    Geburtsjahr: 1964
    >>> type(year_birth)
    <class 'float'>
    
  • Was passiert, wenn ihr einen falschen Werttyp eingebt?

    >>> import datetime
    >>> current = datetime.datetime.now()
    >>> year = current.year
    >>> year_birth = int(input("Geburtsjahr: "))
    Geburtsjahr: Schaltjahr
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: invalid literal for int() with base 10: 'Schaltjahr'
    
  • Schreibt den Code, um für drei User jeweils nach Namen und Alter zu fragen. Nachdem die Werte eingegeben wurden, fragt nach einem der Namen und gebt das zugehörige Alter aus.

    >>> personal_data = {}
    >>> for i in range(3):
    ...     name = input("Name? ")
    ...     age = int(input("Age? "))
    ...     personal_data[name] = age
    ...
    Name? Veit
    Age? 60
    Name? Tim
    Age? 35
    Name? Monique
    Age? 37
    >>> who = input("Who? ")
    Who? Veit
    >>> print(personal_data[who])
    60
    

Schleifen

  • Entfernt aus der Liste x = [ -2, -1, 0, 1, 2, 3], alle negativen Zahlen.

    >>> x = [-2, -1, 0, 1, 2, 3]
    >>> pos = []
    >>> for i in x:
    ...     if i >= 0:
    ...         pos.append(i)
    ...
    >>> pos
    [0, 1, 2, 3]
    
  • Welche List-Comprehension würdet ihr verwenden, um zum selben Ergebnis zu kommen?

    >>> x = [-2, -1, 0, 1, 2, 3]
    >>> pos = [i for i in x if i >= 0]
    >>> pos
    [0, 1, 2, 3]
    
  • Wie würdet ihr die Gesamtzahl der negativen Zahlen in der Liste [-[1, 0, 1], [-1, 1, 3], [-2, 0, 2]] zählen?

    >>> x = [[-1, 0, 1], [-1, 1, 3], [-2, 0, 2]]
    >>> neg = 0
    >>> for row in x:
    ...     for col in row:
    ...         if col < 0:
    ...             neg += 1
    ...
    >>> neg
    3
    
  • Erstellt einen Generator, der nur ungerade Zahlen von 1 bis 10 liefert.

    Tipp

    Eine Zahl ist ungerade, wenn bei der Division durch 2 ein Rest übrig bleibt; also wenn % 2 wahr ist.

    >>> x = (x for x in range(10) if x % 2)
    >>> for i in x:
    ...     print(i)
    ...
    1
    3
    5
    7
    9
    
  • Schreibt ein Dict mit den Kantenlängen und Volumen von Würfeln.

    >>> {x: x**3 for x in range(1, 5)}
    {1: 1, 2: 8, 3: 27, 4: 64}
    

Exceptions

  • Schreibt Code, der zwei Zahlen erhält und die erste Zahl durch die zweite dividiert. Prüft, ob der ZeroDivisionError auftritt, wenn die zweite Zahl 0 ist, und fangt diese ab.

    >>> x = int(input("Please enter an integer: "))
    Please enter an integer: 7
    >>> y = int(input("Please enter an integer: "))
    Please enter an integer: 6
    >>> try:
    ...     z = x / y
    ... except ZeroDivisionError as e:
    ...     print("It cannot be divided by 0!")
    ...
    >>> z
    1.1666666666666667
    >>> y = int(input("Please enter an integer: "))
    Please enter an integer: 0
    >>> try:
    ...     print("It cannot be divided by 0!")
    ... except ZeroDivisionError as e:
    ...     print("It cannot be divided by 0!")
    ...
    It cannot be divided by 0!
    
  • Wenn MyError von Exception erbt, was ist dann der Unterschied zwischen except Exception as e und except MyError as e?

    Die erste fängt jede Ausnahme ab, die von Exception erbt, während die zweite nur MyError-Ausnahmen abfängt.

  • Schreibt ein einfaches Programm, das eine Zahl erhält und dann die Anweisung assert() verwendet, um eine Exception auszulösen, wenn die Zahl 0 ist.

    >>> x = int(input("Please enter an integer that is not zero: "))
    Please enter an integer that is not zero: 0
    >>> assert x != 0, "The integer must not be zero."
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AssertionError: The integer must not be zero.
    
  • Schreibt eine benutzerdefinierte Ausnahme Outliers, die eine Exception auslöst, wenn die Variable x größer oder kleiner als 3 ist?

    >>> class Outliers(Exception):
    ...     pass
    ...
    >>> x = -4
    >>> if abs(x) > 3:
    ...     raise Outliers(f"The value {x} is an outlier")
    ...
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
    Outliers: The value -4 is an outlier
    
  • Handelt es sich bei der Überprüfung, ob ein Objekt eine Liste ist (Check: Listen) um eine Programmierung im Stil von LBYL oder EAFP?

    Das ist LBYL-Programmierung. Erst wenn ihr append() einem try... except-Block packt und TypeError-Exceptions abfangt, wird es etwas mehr EAFP.

Parameter

  • Schreibt eine Funktion, die eine beliebige Anzahl von unbenannten Argumenten annehmen und deren Werte in umgekehrter Reihenfolge ausgeben kann?

    >> def my_func(*params):
    ...     for i in reversed(params):
    ...         print(i)
    ...
    >>> my_func(1, 2, 3, 4)
    4
    3
    2
    1
    

Variablen

  • Angenommen, x = 1, func() setze die lokale Variable x auf 2 und gfunc() die globale Variable x auf 3, welchen Wert nimmt x an, nachdem func() und gfunc() durchlaufen wurden?

    >>> x = 1
    >>> def func():
    ...     x = 2
    ...
    >>> def gfunc():
    ...     global x
    ...     x = 3
    ...
    >>> func()
    >>> x
    1
    >>> gfunc()
    >>> x
    3
    

Module

  • Wenn ihr ein Modul my_math erstellt habt, das eine Funktion divide() enthält, welche Möglichkeiten gibt es, diese Funktion zu importieren und dann zu verwenden? Was sind die Vor- und Nachteile der einzelnen Möglichkeiten?

    >>> import my_math
    >>> my_math.divide(..., ...)
    
    >>> from my_math import divide
    >>> divide(..., ...)
    

    Die erste Lösung wird oft bevorzugt, da es keinen Konflikt zwischen den Bezeichnern in my_math und dem importierenden Namespace geben wird. Diese Lösung ist jedoch ein wenig aufwändiger.

  • Eine Variable min ist im Modul scope.py enthalten. In welchem der folgenden Kontexte kann min verwendet werden?

    1. Mit dem Modul selbst

    2. Innerhalb der Funktion scope() des Moduls

    3. Innerhalb eines Skripts, das das Modul scope.py importiert hat

    1. und 2., aber nicht 3.

  • Packt die Funktionen, die ihr am Ende von Dekoratoren erstellt habt, als eigenständiges Modul. Dabei soll die Funktionen zunächst lediglich von einem anderen Skript aus vollständig nutzbar sein.

    example_mod.py
    from functools import wraps
    
    
    def my_decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            """Wrapper docstring"""
            print("Call decorated function")
            return f(*args, **kwargs)
    
        return wrapper
    
    
    @my_decorator
    def example():
        """Example docstring"""
        print("Call example function")
    
    my_script.py
    from example_mod import example
    
    print(example.__name__)
    print(example.__doc__)
    
  • Macht euer Modul ausführbar.

    --- /home/docs/checkouts/readthedocs.org/user_builds/python-basics-tutorial-de/checkouts/latest/docs/appendix/example_mod.py
    +++ /home/docs/checkouts/readthedocs.org/user_builds/python-basics-tutorial-de/checkouts/latest/docs/appendix/example_mod2.py
    @@ -15,3 +15,8 @@
     def example():
         """Example docstring"""
         print("Call example function")
    +
    +
    +if __name__ == "__main__":
    +    print(example.__name__)
    +    print(example.__doc__)
    
  • Schreibt eure Version des wc-Dienstprogramms so um, dass es sowohl die Unterscheidung zwischen Bytes und Zeichen als auch die Möglichkeit, aus Dateien und von der Standardeingabe zu lesen, implementiert.

    --- /home/docs/checkouts/readthedocs.org/user_builds/python-basics-tutorial-de/checkouts/latest/docs/modules/wcargv.py
    +++ /home/docs/checkouts/readthedocs.org/user_builds/python-basics-tutorial-de/checkouts/latest/docs/modules/wcargv_stdin.py
    @@ -1,27 +1,50 @@
    -"""wc module. Contains function: words_occur()"""
    +"""Reads a file or stdin and returns the number of lines, words and characters –
    +similar to the UNIX wc utility."""
     
     import sys
     
     
    -def words_occur():
    -    """words_occur() - count the occurrences of words in a file."""
    -    # Prompt user for the name of the file to use.
    -    file_name = sys.argv.pop()
    -    # Open the file, read it and store its words in a list.
    -    with open(file_name, "r") as f:
    -        word_list = f.read().split()
    -    # Count the number of occurrences of each word in the file.
    -    occurs_dict = {}
    -    for word in word_list:
    -        # increment the occurrences count for this word
    -        occurs_dict[word] = occurs_dict.get(word, 0) + 1
    -    # Print out the results.
    -    print(
    -        f"File {file_name} has {len(word_list)} words, "
    -        f"{len(occurs_dict)} are unique:"
    -    )
    -    print(occurs_dict)
    +def main():
    +    """Count the occurrences of lines, words and characters in a file or
    +    stdin."""
    +    # initialize counts
    +    line_count = 0
    +    word_count = 0
    +    char_count = 0
    +    filename = None
    +    option = None
    +    if len(sys.argv) > 1:
    +        params = sys.argv[1:]
    +        if params[0].startswith("-"):
    +            # If there are several parameters, the first one is taken as an option
    +            option = params.pop(0).lower().strip()
    +        if params:
    +            filename = params[0]
    +    file_mode = "r"
    +    if option == "-c":
    +        file_mode = "rb"
    +    if filename:
    +        infile = open(filename, file_mode)
    +    else:
    +        infile = sys.stdin
    +    with infile:
    +        for line in infile:
    +            line_count += 1
    +            char_count += len(line)
    +            words = line.split()
    +            word_count += len(words)
    +    if option in ("-c", "-m"):
    +        print(f"{filename} has {char_count} characters.")
    +    elif option == "-w":
    +        print(f"{filename} has {word_count} words.")
    +    elif option == "-l":
    +        print(f"{filename} has {line_count} lines.")
    +    else:
    +        # print the answers using the format() method
    +        print(
    +            f"{filename} has {line_count} lines, {word_count} words and {char_count} characters."
    +        )
     
     
     if __name__ == "__main__":
    -    words_occur()
    +    main()
    

Klassen

  • Schreibt eine Triangle-Klasse, die auch die Fläche berechnen kann.

    class Triangle:
        def __init__(self, width, height):
            self.width = width
            self.height = height
    
        def area(self):
            return 0.5 * self.width * self.height
    

Methoden

  • Schreibt eine Klassenmethode, die ähnlich wie circumferences() ist, aber die Gesamtfläche aller Kreise zurückgibt.

    def area(self):
        return self.diameter**2 / 4 * self.__class__.pi
    
    
    @classmethod
    def areas(cls):
        """Class method to sum all areas."""
        careasum = 0
        for c in cls.circles:
            careasum = careasum + c.area()
        return careasum
    

Klassen und Vererbung

  • Schreibt den Code für eine Triangle-Klasse um, sodass sie von Form erbt.

    >>> class Form:
    ...     def __init__(self, x=0, y=0):
    ...         self.x = x
    ...         self.y = y
    ...
    >>> class Triangle(Form):
    ...     def __init__(self, width=1, height=1, x=0, y=0):
    ...         super().__init__(x, y)
    ...         self.length = length
    ...         self.height = height
    ...
    
  • Wie würdet ihr den Code schreiben, um eine Methode area() für die Klasse Triangle hinzuzufügen? Sollte die Methode area() in die Basisklasse Form verschoben und an Circle, Square und Triangle vererbt werden? Welche Probleme würde diese Änderung verursachen?

    Es ist sinnvoll, die area()-Methode in eine Triangle-Klasse zu packen; aber sie in Form zu packen, wäre nicht sehr hilfreich, weil verschiedene Typen von Form ihre eigenen Berechnungen der Fläche haben. Jede abgeleitete Form würde ohnehin die Basismethode area() überschreiben.

Datentypen als Objekte

  • Was wäre der Unterschied zwischen der Verwendung von type() und isinstance() in Check: Listen?

    Mit type() würdet ihr nur Listen erhalten, nicht aber Instanzen von Listen.

Private Variablen und Methoden

  • Ändert den Code der Klasse Triangle, um die Dimensionsvariablen privat zu machen. Welche Einschränkung wird diese Änderung für die Verwendung der Klasse mit sich bringen?

    >>> class Triangle:
    ...     def __init__(self, x, y):
    ...         self.__x = x
    ...         self.__y = y
    ...
    

    Die Dimensionsvariablen sind außerhalb der Klasse nicht mehr über .x und .y verfügbar.

  • Aktualisiert die Dimensionen der Klasse Triangle, damit sie Eigenschaften mit Getter- und Setter-Methoden sind, die keine negativen Größen zulassen.

    >>> class Triangle:
    ...     def __init__(self, x, y):
    ...         self.__x = x
    ...         self.__y = y
    ...     @property
    ...     def x(self):
    ...         return self.__x
    ...     @x.setter
    ...     def x(self, new_x):
    ...         if new_x >= 0:
    ...             self.__x = new_x
    ...     @property
    ...     def y(self):
    ...         return self.__y
    ...     @y.setter
    ...     def y(self, new_y):
    ...         if new_y >= 0:
    ...             self.__y = new_y
    ...
    >>> t1 = Triangle(-2, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in __init__
    ValueError: The number must be greater or equal to zero.
    >>> t1 = Triangle(2, 2)
    >>> t1.x = -2
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 13, in x
    ValueError: The number must be greater or equal to zero.
    >>> t1.x = 3
    >>> t1.x
    3
    

Verteilungspaket erstellen

  • Wenn ihr ein Paket für eine Aufgabenverwaltung erstellen wollt, das die Aufgaben in eine Datenbank schreibt und über ein Python-API und eine Befehlszeilenschnittstelle (CLI bereitstellt, wie würdet ihr die Dateien strukturieren?

    Das Paket führt drei Arten von Aktionen durch:

    • Zugriffe auf die Datenbank

    • Bereitstellen einer Python-API

    • Bereitstellen einer Befehlszeilenschnittstelle

    ├── README.rst
    ├── pyproject.toml
    └── src
        └── items
            ├── __init__.py
            ├── api.py
            ├── cli.py
            └── db.py
    
  • Überlegt euch, wie ihr die oben genannten Aufgaben erledigen wollt. Welche Bibliotheken und Module fallen euch ein, die diese Aufgabe erfüllen könnten? Skizziert den Code für die Module der Python-API, der Befehlszeilenschnittstelle und der Datenbankanbindung.

    Ich würde in src/items/db.py eine DB-Klasse für die Kommunikation mit der Datenbank erstellen, im folgenden Beispiel zu tinydb:

    import tinydb
    
    
    class DB:
        def __init__(self, db_path, db_file_prefix):
            self._db = tinydb.TinyDB(
                db_path / f"{db_file_prefix}.json", create_dirs=True
            )
    
        def create(self, item: dict):
            """Create an item
    
            Returns:
                id: The items id.
            """
    
            return id
    
        def read(self, id: int):
            """Reads an item.
    
            Args:
                id (int): The item id of an item.
            Returns:
                item: The item object."""
            return item
    
        def update(self, id: int, mods):
            """Update an item in the database.
    
            Args:
                id (int): The item id of an item.
                mods (Item): The modifications to be made to this item.
            """
            self._db.update(changes, doc_ids=[id])
    
        def delete(self, id: int):
            """Deletes an item in the database.
    
            Args:
                id (int): The item id of an item.
            """
            self._db.remove(doc_ids=[id])
    
        def close(self):
            """Closes the database connection."""
            self._db.close()
    

    Dann würde ich in src/items/api dataclass() verwenden, um eine Item-Klasse zu erstellen:

    from dataclasses import dataclass, field
    
    
    @dataclass
    class Item:
        summary: str = None
        owner: str = None
        state: str = "todo"
        id: int = field(default=None, compare=False)
    
    
    class ItemsException(Exception):
        pass
    
    
    class ItemsDB:
        def __init__(self, db_path):
            self._db_path = db_path
            self._db = DB(db_path, ".items_db")
    
        def add_item(self, item: Item):
            return
    
        def get_item(self, item: Item):
            return
    
        def update_item(self, item: Item):
            return
    
        def delete_item(self, item: Item):
            return
    
        def close(self):
            self._db.close()
    
        def path(self):
            return self._db_path
    

    In src/items/__init__.py werden dann ItemsException Item und ItemsDB bereitgestellt:

    from .api import ItemsException, Item, ItemsDB
    

    Siehe auch

    Ein vollständiges Beispiel findet ihr in github.com/veit/items.

Dateien

  • Verwendet die Funktionen des os-Moduls, um einen Pfad zu einer Datei namens example.log zu nehmen und einen neuen Dateipfad im selben Verzeichnis für eine Datei namens example.log1 zu erstellen.

    >>> import os
    >>> path = os.path.abspath("example.log")
    >>> print(path)
    /Users/veit/python-basics-tutorial-de/example.log
    >>> new_path = f"{path}2"
    >>> print(new_path)
    /Users/veit/python-basics-tutorial-de/example.log2
    
  • Welche Bedeutung hat das Hinzufügen von b als Parameter von open()?

    Dadurch wird die Datei im Binärmodus geöffnet, d.h. es werden Bytes und keine Zeichen gelesen und geschrieben.

  • Öffnet eine Datei my_file.txt und fügt zusätzlichen Text am Ende der Datei ein. Welchen Befehl würdet ihr verwenden, um my_file.txt zu öffnen? Welchen Befehl würdet ihr verwenden, um die Datei erneut zu öffnen und von Anfang an zu lesen?

    >>> with open("my_file", "a") as f:
    ...     f.write("Hi, Pythonistas!\n")
    ...
    17
    >>> with open("my_file") as f:
    ...     print(f.readlines())
    ...
    ['Hi, Pythonistas!\n', 'Hi, Pythonistas!\n']
    
  • Welche Anwendungsfälle könnt ihr euch vorstellen, in denen das struct-Modul für das Lesen oder Schreiben von Binärdaten nützlich wäre?

    • beim Lesen und Schreiben einer Binärdatei

    • beim Lesen von einer externen Schnittstelle, wobei die Daten genau so gespeichert werden sollen, wie sie übermittelt wurden

  • Warum könnte pickle für die folgenden Anwendungsfälle geeignet sein oder auch nicht:

    1. Speichern einiger Zustandsvariablen von einem Durchlauf zum nächsten ✅

    2. Aufbewahren von Auswertungsergebnissen ❌, da Pickle abhängig von der jeweiligen Python-Version sind

    3. Speichern von Benutzernamen und Passwörtern ❌, da Pickle nicht sicher sind

    4. Speichern eines großen Wörterbuchs mit englischen Begriffen ❌, da der gesamte Pickle in den Speicher geladen werden müsste

  • Wenn ihr euch die Manpage für das wc-Dienstprogramm anseht, seht ihr zwei Befehlszeilenoptionen:

    -c

    zählt die Bytes in der Datei

    -m

    zählt die Zeichen, die im Falle einiger Unicode-Zeichen zwei oder mehr Bytes lang sein können

    Außerdem sollte unser Modul, wenn eine Datei angegeben wird, aus dieser Datei lesen und sie verarbeiten, aber wenn keine Datei angegeben wird, sollte es aus stdin lesen und verarbeiten.

    Siehe auch

    _wcargv_stdin.py

  • Wenn ein Kontext-Manager in einem Skript verwendet wird, das mehrere Dateien liest und/oder schreibt, welche der folgenden Ansätze wäre eurer Meinung nach am besten?

    1. Legt das gesamte Skript in einen Block, der von einer with-Anweisung verwaltet wird.

    2. Verwendet eine with-Anweisung für alle Lesevorgänge und eine weitere für alle Schreibvorgänge.

    3. Verwendet jedes Mal eine with-Anweisung, wenn ihr eine Datei lest oder schreibt, d.h. für jede Zeile.

    4. Verwendet für jede Datei, die ihr lest oder schreibt, eine with-Anweisung.

    Wahrscheinlich ist 4. der beste Ansatz, da ein Teil der Aufgabe des Kontextmanagers beim Dateizugriff darin besteht, sicherzustellen, dass eine Datei geschlossen ist.

  • Archiviert *.txt-Dateien aus dem aktuellen Verzeichnis im Verzeichnis archive als *.zip-Dateien mit dem aktuellen Datum als Dateiname.

    • Welche Module benötigt ihr hierfür?

      datetime, pathlib und zipfile.

    • Schreibt eine mögliche Lösung.

       1>>> import datetime
       2>>> import pathlib
       3>>> import zipfile
       4>>> file_pattern = "*.txt"
       5>>> archive_path = "archive"
       6>>> today = f"{datetime.date.today():%Y-%m-%d}"
       7>>> cur_path = pathlib.Path(".")
       8>>> paths = cur_path.glob(file_pattern)
       9>>> zip_path = cur_path.joinpath(archive_path, today + ".zip")
      10>>> zip_file = zipfile.ZipFile(str(zip_path), "w")
      11>>> for path in paths:
      12...     zip_file.write(str(path))
      13...     path.unlink()
      14...
      
      Zeile 9

      erstellt den Pfad zur ZIP-Datei im Archivverzeichnis.

      Zeile 10

      öffnet das neue ZIP-Dateiobjekt zum Schreiben; str() wird benötigt, um einen Pfad in eine Zeichenkette umzuwandeln.

      Zeile 12

      schreibt die aktuelle Datei in die Zip-Datei.

      Zeile 13

      entfernt die aktuelle Datei aus dem Arbeitsverzeichnis.