Python statische Variable in Funktion erzeugen, funktioniert nicht

Gast #6954143
Lesenswert?

Hallo zusammen,

Ich komm mir grade ein bisschen Doof vor, brauche in einer Funktion 
mehrere Statische Variablen. Z.B. ob die Serielle-Schnittstelle bereits 
geöffnet ist.

Dazu findet man überall im Internet dass selbe Beispiel:
1
def a():
2
    if not hasattr(a, 'var'):
3
        a.var = 1
4
    var = var + 1
5
    print(var)
6

7
while(1):
8
    a()

Ich würde nun eine Ausgabe aufsteigender Zahlen erwarten, stattdessen 
bekomme ich:
1
var = var + 1
2
UnboundLocalError: local variable 'var' referenced before assignment

Eigentlich sollte var nun nicht nur existieren sondern sogar dauerhaft 
erhalten bleiben.

Immerhin kann ich feststellen dass er ins "if" rein geht, denn bei
1
def a():
2
    if not hasattr(a, 'var'):
3
        a.var = 0
4
        print(var)
5
    var = var + 1
bekomme ich den Fehler
1
print(var)
2
UnboundLocalError: local variable 'var' referenced before assignment

Vielleicht weiss jemand was an diesen immerhin 7 Zeilen Code falsch ist?
Grüße, Matthias
Gast #7012813
Lesenswert?

Matthias schrieb:
> Ich komm mir grade ein bisschen Doof vor, brauche in einer Funktion
> mehrere Statische Variablen. Z.B. ob die Serielle-Schnittstelle bereits
> geöffnet ist.

Was hast Du denn in Wirklichkeit damit vor? Unter Python deutet so ein 
Vorgehen fast immer auf einen Denk- und / oder Designfehler hin. 
Üblicherweise würden eine Klasse oder eine Closure-Funktion verwendet:
1
#!/usr/bin/env python
2

3
def outer():
4
    a = 1
5
    b = 2
6
    def inner(*args, **kwargs):
7
        print('in inner(): a=%s, b=%s'%(a, b))
8
        print('in inner(): args=%s, kwargs=%s'%(args, kwargs))
9
        return a + b
10
    return inner
11

12

13
class Dummi:
14
    def __init__(self, *args, **kwargs):
15
        self.init_args = args
16
        self.init_kwargs = kwargs
17

18
    def __call__(self, *args, **kwargs):
19
        print('in Dummi.__call__(): args=%s, kwargs=%s'%(args, kwargs))
20
        print('in Dummi.__call__(): init_args=%s, init_kwargs=%s'%(self.init_args, self.init_kwargs))
21
        return 4 + 5
22
    
23

24
if __name__ == '__main__':
25
    func = outer()
26
    print('func is %s'%(func))
27
    result = func()
28
    print('result of func() was %s'%(result))
29
    
30
    d = Dummi()
31
    print('d is %s'%(d))
32
    result = d()
33
    print('result of d() was %s'%(result))

Was die Linux-Distribution angeht, so ist das ziemlich egal, ob Du ein 
[KXL]Ubuntu, ein Debian oder etwas aus der RPM-Familie nimmst, oder ein 
Gentoo, Arch, ... Python ist Python, das tut sich nichts, und auch die 
Unterschiede unter den Distributionen sind eher marginal. Es sollte 
vielleicht keine Uralt-Version von Python sein, schon gar kein Python 
2.x, und wenn Du Pythons neuestes Feature benutzen willst, nämlich das 
Structural Pattern Matching, muß es natürlich mindestens das aktuelle 
Python in Version 3.10 sein. Ich glaube allerdings: wenn Du dort 
angekommen bist, werden die großen Distributionen vermutlich auch alle 
Python 3.10 an Bord haben.

Ansonsten herzlich willkommen und viel Spaß, Glück, und Erfolg!
Gast #7012899
Lesenswert?

Ich schließe mich meinen Vorrednern an die statische Variablen für keine 
so gute Idee halten. Wenn man sich einmal an das Konzept von Klassen 
gewöhnt hat, möchte man nicht mehr ohne…
1
#!/usr/bin/python3
2
# -*- coding: UTF-8 -*-
3
class EineKlasse:
4
    def __init__(self):
5
        self.eine_variable = 0
6

7
    def eine_funktion(self):
8
        self.eine_variable = self.eine_variable + 1
9
        return self.eine_variable
10

11
ek = EineKlasse()
12
while True:
13
    print(ek.eine_funktion())
#7012981
Lesenswert?

Norbert schrieb:
> Ich schließe mich meinen Vorrednern an die statische Variablen für keine
> so gute Idee halten. Wenn man sich einmal an das Konzept von Klassen
> gewöhnt hat, möchte man nicht mehr ohne…

Ja, richtig. Es erschließt sich mir auch nicht, warum man in einer 
objektorientierten Sprache wie Python -- das die Objektorientierung 
obendrein besonders einfach macht -- mit so häßlichen Hacks wie der 
Metaprogrammierung oben versuchen wollen würde, die Verwendung von 
Klassen zu vermeiden?!
#7013174
Lesenswert?

Ein T. schrieb:
> ...Es erschließt sich mir auch nicht, warum man in einer
> objektorientierten Sprache wie Python -- das die Objektorientierung
> obendrein besonders einfach macht -- mit so häßlichen Hacks wie der
> Metaprogrammierung oben versuchen wollen würde, die Verwendung von
> Klassen zu vermeiden?!
Vermutlich weil man das Konzept der Objektorientierung noch nicht kennt 
oder verstanden hat.

@TO: Auch ich würde Dir raten, die damit zu befassen, es lohnt sich, ;)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren