Python Scopes

Wo ein Name im Programm sichtbar ist

print('Hi Fred!')
> 
print('Hi Fred!')
> Hi Fred!
name = 'Fred'

def say_hi():
    print(f'Hi {name}!')

say_hi()
> Hi Fred!
name = 'Fred'

def say_hi():
    name = 'Melanie'
    print(f'Hi {name}!')

say_hi()
print(name)
> 
name = 'Fred'

def say_hi():
    name = 'Melanie'
    print(f'Hi {name}!')

say_hi()
print(name)
Z5> Hi Melanie!
Z8> Fred
name = 'Fred'

def say_hi():
    name = 'Melanie'
    print(f'Hi {name}!')

say_hi()
print(name)
Z5> Hi Melanie!
Z8> Fred
sound = 'beep'

def beep():
    print(sound)

def bang():
    sound = 'bang'
    beep()
    print(sound)

bang()
> 
sound = 'beep'

def beep():
    print(sound)

def bang():
    sound = 'bang'
    beep()
    print(sound)

bang()
> beep
> bang

Lokal?

JA

NEIN

Global?

JA

NEIN?

Text

Scopes  [Gültigkeitsbereiche]

Lokal?

JA

NEIN

Global?

JA

NEIN

Built In?

JA

Scopes  [Gültigkeitsbereiche]

Scope [Gültigkeitsbereich]

Ermöglichen die Verwendung von Bibliotheken!

Beispiel: Ãœberschreiben von print()

_print = print

def print(n):
    _print('$$', n)

print('Hello')
> $$ Hello

Aber...

def configure():
    _print = print
    def print(n):
        _print('$$', n)

configure()
print('hello')
> 

Aber...

def configure():
    _print = print
    def print(n):
        _print('$$', n)

configure()
print('hello')
Traceback (most recent call last):
  File "/snippets/scopes-demo.py", line 7, in <module>
    say_hi()
  File "/snippets/scopes-demo.py", line 3, in say_hi
    print(f'Hi {name}')
UnboundLocalError: local variable 'print' referenced before assignment

...nur im global scope möglich

Fix...

def configure():
    global print
    _print = print
    def print(n):
        _print('$$', n)

configure()
print('Hello')
> $$ Hello

Änderungen ausserhalb des aktuellen Scopes?

name = 'Fred'

def say_hi():
    global name
    name = 'Melanie'
    print(f'Hi {name}!')

say_hi()
print(name)
>
name = 'Fred'

def say_hi():
    global name
    name = 'Melanie'
    print(f'Hi {name}!')

say_hi()
print(name)
Z5> Hi Melanie!
Z9> Melanie
names = ['Fred']

def say_hi():
    names[0] = 'Melanie'
    print(f'Hi {names[0]}!')

print(names)
say_hi()
print(names)
>

Was passiert hier?

names = ['Fred']

def say_hi():
    # names: Referenz auf den
    # Speicherbereich der Liste
    # --> Die Referenz wird NICHT
    # verändert!
    names[0] = 'Melanie'
    print(f'Hi {names[0]}!')

print(names)
say_hi()
print(names)
Z7> ['Fred']
Z5> Hi Melanie!
Z9> ['Melanie']
math = [3.5, 5, 6, 4.5, 5.25]
franz = [3, 3.75, 3.1, 4]

def prettify(grades):
    for nr in range(len(grades)):
        if grades[nr] < 4:
            grades[nr] = 5

prettify(math)
prettify(franz)
print(math)
print(franz)
>
math = [3.5, 5, 6, 4.5, 5.25]
franz = [3, 3.75, 3.1, 4]

def prettify(grades):
    for nr in range(len(grades)):
        if grades[nr] < 4:
            grades[nr] = 5

prettify(math)
prettify(franz)
print(math)
print(franz)
> [5, 5, 6, 4.5, 5.25]
> [5, 5, 5, 4]

Shadowing [Ãœberschatten]

Der innere Scope überschreibt (überschattet) den äusseren Scope

Shadowing [Ãœberschatten]

Der innere Scope überschreibt (überschattet) den äusseren Scope

 

Was passiert mit Parametern?

def say_hi(name):
    name = f'{name}{name[-1]}y'
    print(f'Hi {name}!')

say_hi('Fred')
say_hi('John')
>
def say_hi(name):
    # name[-1] gibt den letzten
    # Buchstaben zurück
    name = f'{name}{name[-1]}y'
    print(f'Hi {name}!')

say_hi('Fred')
say_hi('John')
> Hi Freddy!
> Hi Johnny!

In der Praxis...

  • Möglichst eindeutige Namen verwenden
  • Vermeiden von Änderungen von globalen Variablen
  • Lokale Variablen (statt globale) verwenden
  • Abgeschlossene Funktionen schreiben
    • Parameter verwenden, um Werte zu übergeben
    • Return verwenden, um Werte zurückzugeben