None
ist ein Singleton:
None
-Objekt innerhalb eines laufenden Python-ProgrammsDas Schlüsselwort is
vergleicht in Python, ob sich zwei Referenzen / Namen auf das gleiche Objekt beziehen.
a = [1, 2]
b = a
x = [1, 2]
a == b # True
a is b # True
a == x # True
a is x # False
Nachdem None
ein Singleton ist, kann darauf mit is None
getestet werden.
if a is None:
...
True
oder False
a = True
if a:
print('hello')
Intern verhält sich False
fast wie 0
und True
fast wie 1
False + True # 1
10 // 3
10 % 3
2 ** 3
um uns beim Lesen langer Zahlen zu helfen:
earth_circumference = 40075017
earth_circumference = 40_075_017
beliebig große Ganzzahlen
Andere Zahlensysteme:
a = 42 # decimal
b = 0b101010 # binary
c = 0o52 # octal
d = 0x2a # hexadecimal
e = int('101010', 2)
64-bit Gleitkommazahlen
a = 2.3
b = .2
c = 6e23
d = float('nan')
e = float('inf')
Rundungsfehler: manche Zahlen können nicht als Gleitkommazahlen dargestellt werden, sie sind immer Annäherungen
Beispiele im Dezimalsystem: 1/3, 1/7, π
Beispiele im Binärsystem (floats): 1/10, 1/5, 1/3, π
Beispiel: π + π ergibt 6.2
, wenn wir Dezimalzahlen mit 2 Stellen verwenden (besseres Ergebnis wäre 6.3
)
Beispiel: 0.1 + 0.2
ergibt ~ 0.30000000000000004
, wenn wir 64-bit floats verwenden
0.1 + 0.2 == 0.3
# False
import math
math.isclose(0.1 + 0.2, 0.3)
# True
IEEE 754: Standard für Gleitkommazahlen am Computer
wird von Python großteils umgesetzt
Ausnahme: Python löst für manche Operationen Exceptions aus, die unter dem Standard ein Ergebnis liefern würden - z.B. 1.0/0.0
Besondere Zahlen in IEEE 754:
inf
und -inf
(unendliche Werte)nan
(not-a-number: undefinierter / unbekannter Wert)a = 2 + 3j
Zu binären Operatoren gibt es sogenannte erweiterte Zuweisungen (augmented assignments):
a = a + 1
Kurzform (erweiterte Zuweisung):
a += 1
Weitere Formen: -=
, *=
, ...
Unicode: Katalog von über 100000 internationalen Schriftzeichen, jedes mit eindeutigem Namen und Nummer (meist in Hexadezimalform)
Beispiele:
Zeichenkodierung = Zuordnung von Zeichen zu Bitsequenzen
Eine Zeichenkodierung ist notwendig, um Text auf ein Speichermedium zu schreiben oder über das Netzwerk zu übertragen
Beispiele in ASCII / Latin1 / UTF-8:
!
↔ 00100001
A
↔ 01000001
a
↔ 01100001
Beispiele in Latin1:
Ä
↔ 11000100
Beispiele in UTF-8:
Ä
↔ 11000011 10100100
🙂
↔ 11110000 10011111 10011001 10000010
UTF-8 hat sich insbesondere im Web zum Standardencoding entwickelt
Die ersten 128 Unicode-Zeichen benötigen nur 8 Bit (wie bei ASCII / Latin1)
Alle anderen Zeichen benötigen jeweils 16, 24 oder 32 Bit
UTF-32 kodiert unmittelbar die Unicode-Codepukte, wobei je nach Anwendungsbereich eine andere Bytereihenfolge (big endian oder little endian) auftreten kann.
Beispiel:
🙂 (U+1F642) ↔ 00 01 F6 42
(big endian) oder 42 F6 01 00
(little endian)
Zeilenumbrüche können durch die Zeichen LF
(line feed, U+000A
) bzw CR
(carriage return, U+000D
) kodiert werden
LF
: Standard unter Linux, MacOSCRLF
: Standard unter Windows, in Netzwerkprotokollen wie HTTPIn String-Literalen wird LF
oft durch \n
und CR
oft durch \r
repräsentiert
Strings in Python sind Zeichenfolgen, die jedes Unicodezeichen repräsentieren können
Beispiele:
a = "test"
b = 'test'
a = """this
is a multi-line
string literal.
"""
Mit Hilfe des Backslashes können besondere Zeichen eingefügt werden:
a = "He said:\n\"Hi!\""
\'
→ '
\"
→ "
\\
→ \
\n
→ Line Feed (Zeilenumbruch unter Unix)\r\n
→ Carriage Return + Line Feed (Zeilenumbruch unter Windows)\t
→ Tab\xHH
bzw. \uHHHH
bzw. \UHHHHHHHH
→ Unicode-Codepunkt (hexadezimal)Wenn in einem String keine Escape Sequenzen benötigt werden:
path = r"C:\documents\foo\news.txt"
(besonders nützlich bei regulären Ausdrücken)
.lower()
.upper()
.startswith(...)
.endswith(".txt")
.center(10)
.ljust(10)
.rjust(10)
.strip()
.split(' ')
.splitlines()
.join()
Quellen:
Original:
Ihr naht euch wieder, schwankende Gestalten,
Die früh sich einst dem trüben Blick gezeigt.
Ziel:
Ihr naht euch wieder, schwankende Gestalten, 1
Die früh sich einst dem trüben Blick gezeigt. 2
Aufgaben:
String-Formatierung = Einsetzen von Werten in Strings
Möglichkeiten:
greeting = "Hello, " + name + "!"
greeting = f"Hello, {name}!"
city = 'Vienna'
temperature = 23.7
# eher veraltet
'weather in %s: %f°C' % (city, temperature)
'weather in {0}: {1}°C'.format(city, temperature)
'weather in {}: {}°C'.format(city, temperature)
'weather in {c}: {t}°C'.format(c=city, t=temperature)
f'weather in {city}: {temperature}°C'
.4f
: vier Dezimalstellen nach dem Dezimalzeichen.4g
: vier Dezimalstellenprint(f"Pi is {math.pi:.4f}")
# Pi is 3.1416
print(f"Pi is {math.pi:.4g}")
# Pi is 3.142
>8
: rechtsbündig (Gesamtbreite 8)^8
: zentriert<8
: linksbündigprint(f"{first_name:>8}")
print(f"{last_name:>8}")
John
Doe
Kombination:
print(f"{menu_item:<12} {price:>5.2}$")
Burger 11.90$
Salad 8.90$
Fries 3.90$
weitere Optionen:
Listen sind veränderliche Sequenzen von Objekten; sie werden üblicherweise verwendet, um gleichartige (homogene) Einträge abzulegen
primes = [2, 3, 5, 7, 11]
users = ["Alice", "Bob", "Charlie"]
Die folgenden Operationen klappen auch bei anderen Sequenzen - z.B. Tupeln, Strings oder Bytes
users[2]
users[2:4]
users + users
3 * users
len(users)
for user in users:
if 'Tim' in users:
Listen können direkt verändert werden (im Gegensatz zu Tupeln, Strings):
users.append("Dan")
users.insert(2, "Max")
users.pop()
users.pop(2)
Sortierung nach Standardreihenfolge (bei Strings alphabetisch)
l.sort()
Sortierung nach selbstdefinierten Reihenfolgen:
l.sort(key=len)
def count_a(s):
return s.count("a")
l.sort(key=count_a)
Erstellung: Einträge werden mit Kommas getrennt, üblicherweise mit runden Klammern umschlossen.
empty_tuple = ()
single_value = ('Thomas', )
single_value = 'Thomas',
two_values = ('Thomas', 'Smith')
two_values = 'Thomas', 'Smith'
time = (23, 45, 0)
hour, minute, second = time
Tauschen von Variablennamen:
a, b = b, a
beim Lesen von Datenträgern oder Empfangen von Daten müssen wir manchmals mit Bytes arbeiten: Abfolgen von Zahlen im Bereich von 0 bis 255 (8 Bit)
Bytes können Bilder, Text, Daten, ... repräsentieren
Bytes werden oft in Hexadezimalnotation statt dezimal geschrieben:
hex-Literale in Python:
0x1
0x9
0xa
0xf
0x10
0x11
0x1f
0x20
Erstellen von Bytes aus einer Liste von Zahlen:
a = bytes([0, 64, 112, 160, 255])
b = bytes([0, 0x40, 0x70, 0xa0, 0xff])
Erstellen von Bytes aus einem Byte String-Literal:
c = b"\x00\x40\x70\xa0\xff"
ASCII-Werte können direkt verwendet werden (\x40
= "@", \x70
= "p"):
d = b"\x00@p\xa0\xff"
Standard Repräsentation in Python:
print(bytes([0x00, 0x40, 0x70, 0xa0]))
b'\x00@p\xa0\xff'
Wenn möglich werden bytes als ASCII-Zeichen dargestellt; sonst wird ihr Hexadezimalcode angezeigt
Bytes beinhalten of codierten Text
Wenn wir das Encoding kennen, können wir zwischen Bytes und Strings wechseln:
'ä'.encode('utf-8')
# b'\xc3\xa4'
b'\xc3\xa4'.decode('utf-8')
# 'ä'
Sequenzen sind Objekte, die aus einer Aufreihung anderer Objekte bestehen, z.B.:
s[2]
s[2:4]
s + t
3 * s
len(s)
for el in s:
if el in s:
Elementzugriff
users = ['mike', 'tim', 'theresa']
users[0] # 'mike'
users[-1] # 'theresa'
Änderung von Elementen (falls Sequenz veränderlich ist)
users = ['mike', 'tim', 'theresa']
users[0] = 'molly'
Zugriff auf mehrere Elemente
users = ['mike', 'tim', 'theresa']
users[0:2] # ['mike', 'tim']
Konkatenation
users = ['mike', 'tim', 'theresa']
new_users = users + ['tina', 'michelle']
Wiederholung
users = ['mike', 'tim', 'theresa']
new_users = users * 3
Länge
users = ['mike', 'tim', 'theresa']
print(len(users))
for-Schleife
users = ['mike', 'tim', 'theresa']
for user in users:
print(user.upper())
Dictionaries sind Zuordnungen, die bestimmten Einträgen zugehörige Werte zuweisen.
person = {
"first_name": "John",
"last_name": "Doe",
"nationality": "Canada",
"birth_year": 1980
}
Elementzugriff bei dictionaries
person["first_name"] # "John"
Iteration über Dictionaries
for entry in person:
print(entry)
Dies liefert die Schlüssel: "first_name"
, "last_name"
, "nationality"
, "birth_year"
Seit Python 3.7 bleiben die Schlüssel garantiert in der ursprünglichen Reihenfolge
Iteration über Schlüssel/Werte - Paare:
for key, value in person.items():
print(f'{key}, {value}')
d = {0: 'zero', 1: 'one', 2: 'two'}
d[2]
d[2] = 'TWO'
d[3] # KeyError
d.get(3) # None
d.setdefault(2, 'n')
d.setdefault(3, 'n')
d.keys()
d.items()
d1.update(d2)
Jedes unveränderliche Objekt kann als Key verwendet werden - meistens sind es Strings
a = 20
a.to_bytes(1, "big")
"hello".upper()
message = "hello"
type(message)
isinstance(message, str)
Klassen können verschiedenste Dinge repräsentieren, z.B.:
Definition einer Klasse umfasst üblicherweise:
Beispiel: Klasse TextIOWrapper
kann eine Textdatei repräsentieren (wird beim Aufruf von open()
erstellt)
Attribute:
Methoden:
Beispiel: Klasse BankAccount
class MyClass():
# die Methode __init__ initialisiert das Objekt
def __init__(self):
# self bezieht sich in jeder Methode
# auf die aktuelle Instanz
self.message = "hello"
instance = MyClass()
instance.message # "hello"
Kennzeichnung von Attributen und Methoden, die von außen nicht verwendet werden sollten mit _
We're all consenting adults here: https://mail.python.org/pipermail/tutor/2003-October/025932.html
Achtung: oft Fehlinformation bezüglich __
! In der Praxis sollten doppelte Unterstriche kaum verwendet werden.
a = Length(2.54, "cm")
b = Length(3, "in")
a.unit
a.value
tdl = TodoList("groceries")
tdl.add("milk")
tdl.add("bread")
print(tdl.todos)
tdl.todos[0].toggle()
tdl.stats() # {open: 1, completed: 1}
öfters verwenden wir eine Klasse als Basis für eine andere Klasse
z.B.:
User
-Klasse als Basis der AdminUser
-KlasseTicTacToeGame
als Basis von TicTacToeGameGUI
Vererbung: ein AdminUser
ist ein User
Komposition: TicTacToeGameGUI
könnte TicTacToeGame
im Hintergrund verwenden
häufiges Mantra: Composition over Inheritance: verwende Vererbung nicht zu sehr
Vererbung:
class User():
...
class AdminUser(User):
...
die AdminUser
-Klasse erbt automatisch alle bestehenden Methoden der User
-Klasse
Komposition:
class TicTacToeGame():
...
class TicTacToeGameGUI():
def __init__(self):
self.game = TicTacToeGame()
Beispiel zur Vererbung - Datenbankmodell in Django:
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
Standard-Stil für Python-Code
offizielles Dokument: https://www.python.org/dev/peps/pep-0008/
cheatsheet: https://gist.github.com/RichardBronosky/454964087739a449da04
In VS Code-Einstellungen: "python.formatting.provider": "black"
input:
a='Hello'; b="Have you read \"1984\"?"
c=a[0+1:3]
output via black:
a = "Hello"
b = 'Have you read "1984"?'
c = a[0 + 1 : 3]
Auszüge aus dem Zen of Python (anzeigbar via import this
):
Dokumentationsstrings, die z.B. Funktionen genauer beschreiben
Kommentare in einer Funktion: helfen Programmierern, die an dieser Funktion arbeiten
Docstring einer Funktion: hilft Programmierern, die diese Funktion verwenden
Beispiel:
def fib(n):
"""Compute the n-th fibonacci number.
n must be a nonnegative integer
"""
...
help(fib)
help(round)
Breakpoints (Haltepunkte) können gesetzt werden, um die Ausführung des Codes an diesem Punkt zu pausieren.
Möglichkeiten, um Breakpoints zu setzen:
breakpoint()
(seit Python 3.7)Ausführung in VS Code:
Manuell weiterspringen:
c
für continue im Python Debuggerq
für quit im Python DebuggerManuell weiterspringen:
n
für next im Python Debuggers
für step im Python Debuggerr
für return im Python DebuggerWerte in VS Code begutachten:
Ausgabe von Werten im Python Debugger mittels p
für print:
p mylist
p mylist[0]
if
while
for ... in ...
for ... in range(...)
try ... except ...
wir erinnern uns:
if age_seconds < 1000000000:
print("You are less than 1 billion seconds old")
else:
print("You are older than 1 billion seconds")
Bei Kriterien für if
und while
verwenden wir üblicherweise Ausdrücke, die bei der Auswertung boolesche Werte ergeben.
Wir könnten jedoch auch andere Typen verwenden:
a = 0
if a: ...
name = input("enter your name")
if name: ...
products = []
if products: ...
Diese Typen werden in boolesche Werte konvertiert bevor sie als Kriterium herangezogen werden.
Grundsätzlich können beliebige Werte als Kriterium verwendet werden. Die meisten sind dabei "truthy".
Folgende Werte gelten als "falsy" - ein Aufruf von bool(...)
liefert False
zurück:
False
0
, 0.0
None
""
, []
, ()
, {}
)datetime.time(0, 0, 0)
)nicht "pythonic":
name = input("Enter your name:")
if name != "":
...
"pythonic":
name = input("Enter your name:")
if name:
...
Überprüfen, ob age
im Bereich 13-19 liegt:
13 <= age and age <= 19
kürzere Version:
13 <= age <= 19
Überprüfen, ob a
und b
beide 0
sind (kurze Version):
a == b == 0
Ein Ausdruck, der einen von zwei möglichen Werten ergibt - basierend auf einem booleschen Kriterium
size = 'small' if length < 100 else 'big'
In anderen Sprachen:
// JavaScript
size = length < 100 ? 'small' : 'big';
Wiederholung: Entpacken von Tupeln
time = (23, 45, 0)
hour, minute, second = time
Aufzählen von Listenelementen:
l = ['Alice', 'Bob', 'Charlie']
for i, name in enumerate(l):
print(f'{i}: {name}')
Enumerate gibt eine Datenstruktur zurück, die sich wie die folgende Liste verhält:
[(0, 'Alice'), (1, 'Bob'), (2, 'Charlie')]
Auflisten von Ordnerinhalten (inklusive Unterodner) mittels os.walk
:
import os
for directory, dirs, files in os.walk("C:\\"):
print(f"{directory} {files}")
C:\ []
C:\PerfLogs []
C:\Program Files []
C:\ProgramData []
...
Schlüsselwort continue
: kann verwendet werden, um den Rest der aktuellen Iteration einer Schleife zu überspringen
Beispiel:
for name in os.listdir("."):
if not name.endswith(".txt"):
# skip .txt files
continue
# process other files here
Wichtige Möglichkeit, um Listen basierend auf anderen Listen zu erstellen
In anderen Programmiersprachen oft umgesetzt mittels map
und filter
/ grep
Umwandeln der Einträge:
names = ["Alice", "Bob", "Charlie"]
uppercase_names = [name.upper() for name in names]
Resultat:
["ALICE", "BOB", "CHARLIE"]
Filtern:
amounts = [10, -7, 8, 19, -2]
positive_amounts = [amount for amount in amounts if amount > 0]
result:
[10, 8, 19]
Allgemeine Syntax:
new_list = [new_entry for entry in old_list]
new_list = [new_entry for entry in old_list if condition]
colors = {
'red': '#ff0000',
'green': '#008000',
'blue': '#0000ff',
}
m_colors = { color: colors[color][1:] for color in colors}
or
m_colors = {
name: value[1:] for name, value in colors.items()
}
Übung: versuche, jede der obigen Exceptions auszulösen
age_str = input("Enter your age")
try:
age = int(age_str)
except ValueError:
print("Could not parse input as number")
age_str = input("Enter your age")
try:
age = int(age_str)
except ValueError as e:
print("Could not parse input as number")
print(e)
print(e.args)
Mehrere Arten von Exceptions abfangen:
try:
file = open("log.txt", encoding="utf-8")
except FileNotFoundError:
print("could not find log file")
except PermissionError:
print("reading of file is not permitted")
except Exception:
print("error when reading file")
Einsatz von finally
:
try:
file = open("log.txt", "w", encoding="utf-8")
file.write("abc")
file.write("def")
except IOError:
print("Error when writing to file")
finally:
file.close()
Einsatz von else
:
try:
file = open("log.txt", "w", encoding="utf-8")
except IOError:
print("could not open file")
else:
# no errors expected here
file.write("abc")
file.write("def")
file.close()
LBYL: Look before you leap
EAFP: It's easier to ask for forgiveness than permission
(Beispiel: Parsen von Zahlen)
raise ValueError('test')
try:
...
except ClientError as e
if "DryRunOperation" not in str(e):
raise
Eigene Exceptions können wir als Unterklassen von Exception
definieren
class MoneyParseException(Exception):
pass
raise MoneyParseException()
Modul als Verzeichnis:
- foo/
- __init__.py
# __init__.py
a = 1
b = 2
Modul als Ordner mit separaten Definitionen:
- foo/
- __init__.py
- _a_mod.py
- _b_mod.py
# __init__.py
from foo._a_mod import a
from foo._b_mod import b
Alle Pfade für Imports sehen wir via:
import sys
print(sys.path)
Importierte Module werden in kompilierter Form abgelegt, um später schneller eingelesen werden zu können.
Wir finden die kompilierten Versionen im Ordner __pycache__
in einem importierten Module bezieht sich die Variable __name__
auf dessen Namen
wurde eine Python-Datei direkt ausgeführt und nicht importiert, ist deren __name__
gleich "__main__"
if __name__ == "__main__":
print("this file was run directly (and not imported)")
installing a package via PIP:
pip install cowsay
installing a specific version:
pip install cowsay==6.1
installing a compatible version (this could also install versions 6.2, 6.3, etc. - if they are available):
pip install cowsay~=6.1
virtual environments: allow for installing different dependencies and dependency versions for different projects
creating a virtual environment (typically named ".venv"):
python -m venv .venv
will create a new folder ".venv/" which contains the virtual environment
activating an environment on Windows:
./.venv/Scripts/activate
deactivating a venv:
deactivate
if necessary: enable execution of local scripts on Windows - from an admin terminal:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
"old" configuration file: requirements.txt
"new" configuration file: pyproject.toml
example requirements.txt:
cowsay~=6.1
requests~=2.30
installation from requirements.txt:
pip install -r requirements.txt
example pyproject.toml:
[project]
name = "my-python-project"
version = "1.0"
dependencies = [
"cowsay~=6.1",
"requests~=2.30",
]
installation:
pip install .
def foo(*args, **kwargs):
print(args)
print(kwargs)
foo("one", "two", x="hello")
# args: ("one", "two")
# kwargs: {"x": "hello"}
args
ist ein Tupel, kwargs
ein Dictionary.
Aufgabe: "Nachbau" von range()
mit Hilfe einer while-Schleife
numbers = ["one", "two", "three"]
# equivalent:
print(numbers[0], numbers[1], numbers[2])
print(*numbers)
global
/ nonlocal
Spielt beim Zuweisen von Variablen eine Rolle
Beispiel: Schere, Stein, Papier
import random
wins = 0
losses = 0
def play_rock_paper_scissors():
player = input("rock, paper or scissors?")
opponent = random.choice(["rock", "paper", "scissors"])
if player == opponent:
pass
elif (
(player == "rock" and opponent == "scissors")
or (player == "paper" and opponent == "rock")
or (player == "scissors" and opponent == "paper")
):
global wins
wins += 1
else:
global losses
losses += 1
while input("play? (y/n)") != "n":
play_rock_paper_scissors()
print(f"won: {wins}, lost: {losses}")
Eine bessere Alternative zum Keyword global
ist oft das Verwenden einer Klasse:
import random
class RockPaperScissors():
def __init__(self):
self.wins = 0
self.losses = 0
def play(self):
...
def run(self):
while input("play? (y/n)") != "n":
self.play()
print(f"won: {wins}, lost: {losses}")
Was ist der Wert von a
am Ende dieses Programms?
a = [1, 2, 3]
b = a
b.append(4)
Eine Zuweisung (z.B. b = a
) versieht ein existierendes Objekt mit einem neuen (zusätzlichen) Namen.
Im Hintergrund steht nach wie vor nur ein einzelnes Objekt.
Durch das Ausführen von b = a
entsteht einen zusätzliche Referenz, die sich auf das selbe Objekt bezieht.
Operationen, die zum Setzen zusätzlicher Referenzen führen:
b = a
)myfunc(a)
- es entsteht eine neue funktionsinterne Referenz)mylist.append(a)
)Der Aufruf einer Funktion mit einem Objekt als Parameter versieht dieses Objekt mit einer weiteren Referenz (call by sharing).
def foo(a_inner):
print(id(a_inner))
a_outer = []
foo(a_outer)
print(id(a_outer))
reine Funktionen: Funktionen, die mit ihrer Umgebung nur dadurch interagieren, dass sie Parameter entgegennehmen und Werte zurückgeben
Side Effects (Nebeneffekte, Seiteneffekte): Aktionen einer Funktion, die die Umgebung verändern
häufige Side Effects:
Side Effects, die üblicherweise vermieden werden:
Vorteile reiner Funktionen:
Beispiel einer nicht-idealen Funktion, die ein Argument (formats) verändert:
def list_files_by_formats(path, formats):
if "jpg" in formats:
formats.append("jpeg")
files = []
for file in os.listdir(path):
for format in formats:
if file.endswith("." + format):
files.append(file)
break
return files
formats = ["jpg", "png"]
print(list_files_by_formats(formats))
print(formats)
# will print: ["jpg", "png", "jpeg"]
"korrektere" Implementierung:
def list_files_by_formats(path, formats):
if "jpg" in formats:
formats = formats.copy()
formats.append("jpeg")
# ...
das folgende wäre ein Anti-Pattern (eine Funktion, die Argumente abändert):
mylist = [2, 1, 3]
sort(mylist)
print(mylist)
# [1, 2, 3]
tatsächliche Möglichkeiten zum Sortieren in Python:
reine Funktion:
print(sorted(mylist))
Methode, die ein Objekt abändert:
mylist.sort()
print(mylist)
Unerwartetes Verhalten in Python, wenn Standardparameter abgeändert werden:
def list_files_by_formats(path, formats=["gif", "jpg", "png"]):
if "jpg" in formats:
formats.append("jpeg")
# ...
list_files_by_formats(".")
# formats: ["gif", "jpg", "png", "jpeg"]
list_files_by_formats(".")
# formats: ["gif", "jpg", "png", "jpeg", "jpeg"]
(Web-Suche: mutable default arguments)
Python 2 vs Python 3
Tiefgreifende Änderung in Python 3:
Strikte Trennung von Text (strings) und Binärdaten (bytes)
in Python 2: Datentypen bytes
, str
und unicode
Python 2:
print "a",
Python 3:
print("a", end="")
Python 2:
10 / 3 # 3
in Python 2: range()
liefert Liste zurück, xrange()
liefert speicherschonendes Objekt
in Python 3: range()
liefert speicherschonendes Objekt
in Python 2: input()
wertet die Eingabe aus, raw_input()
gibt String zurück
in Python 3: input()
gibt String zurück
Verhalten von Python 3 in Python 2 übernehmen:
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
Kompatibilitätsschicht zwischen Python 2 und Python 3
Unterstützung von Python 2 und Python 3 aus der gleichen Codebase