Forum: PC-Programmierung Python statische Variable in Funktion erzeugen, funktioniert nicht


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Matthias (Gast)


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

von MaWin. (Gast)


Lesenswert?

Matthias schrieb:
> var = var + 1
1
a.var = a.var + 1
2
print(a.var)

von Rolf M. (rmagnus)


Lesenswert?

Warum wird es hier:

Matthias schrieb:
> a.var = 1

als a.var referenziert, aber hier

> var = var + 1

nur als var?

von Nur_ein_typ (Gast)


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!

von Norbert (Gast)


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())

von Ein T. (ein_typ)


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?!

von M.A. S. (mse2)


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, ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.