Vinnaren i pepparkakshustävlingen!
  • 1
  • 2
2022-11-20, 19:25
  #1
Medlem
Har precis fått upp ögonen för programmering och programmerat lite python på senaste tiden.
Mitt första projekt är att göra en suppersimpelt kodlås med 4 knappar kopplade till GPIO på raspberry pi.

Jag har en variabel som jag sätter vid uppstart av filen:
fail1 = False

funktionen failed_one() skall ändra fail1 till fail1 = True, detta är i sin tur villkoren för att nästa misslyckade kod ska generera fail2 = True.

Problemet är att efter att den kört failed_one() så är fail1 = False fortfarande.

Vad är det jag missförstår här?


Kod:
#import libraries
import RPi.GPIO as GPIO
import time

#GPIO Basic initialization
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#LCD
from lcd_api import LcdApi
from i2c_lcd import I2cLcd
 
I2C_ADDR = 0x27
I2C_NUM_ROWS = 4
I2C_NUM_COLS = 20

lcd = I2cLcd(1, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)


led1 = 21
led2 = 20
led3 = 16
led4 = 12
button1 = 26
button2 = 19
button3 = 13
button4 = 6

#Initialize your pin
GPIO.setup(led1,GPIO.OUT)
GPIO.setup(led2,GPIO.OUT)
GPIO.setup(led3,GPIO.OUT)
GPIO.setup(led4,GPIO.OUT)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(6, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)


digit0=False
digit1=False
digit2=False
digit3=False
digit4=False
button1=False
button2=False
button3=False
button4=False
fail1=False
print("debug1")
fail2=False
GPIO.output(led1,0)
GPIO.output(led2,0)
GPIO.output(led3,0)
GPIO.output(led4,0)

code=dict([(26,0),(19,0),(13,0),(6,0)])
print(code)

validcode=[26,19,13,6]

lcd.clear()
lcd.move_to(0,0)
lcd.putstr("Enter Code")

clickedbuttons=[]

def correct():
    GPIO.output(led1,1)
    GPIO.output(led2,0)
    GPIO.output(led3,0)
    GPIO.output(led4,0)
    fail1 = False
    print("debug2")
    fail2 = False
    clickedbuttons.clear()
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("Correct")
    print("Correct")
    time.sleep(5)
    GPIO.output(led1,0)
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("Enter Code")

def failed_one():
    print("incorrect1")
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("Fail 1/3")
    GPIO.output(led2,1)
    clickedbuttons.clear()
    fail1 = True
    print(fail1)
    
def failed_two():
    print("incorrect2")
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("Fail 2/3")
    GPIO.output(led3,1)
    clickedbuttons.clear()
    fail2 = True
    
def failed_three():
    print("incorrect3")
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("Fail 3/3")
    lcd.move_to(1,0)
    lcd.putstr("5 min timeout")
    GPIO.output(led4,1)
    clickedbuttons.clear()
    time.sleep(10)
    fail1 = False
    print("debug3")
    fail2 = False



#FIRST ATTEMPT
while True:
    print(fail1)
    for key in code:
        if GPIO.input(key) and code[key] == 0:
            clickedbuttons.append(key)
            code.update({key:1})
            time.sleep(0.2)
        elif code[key] == 1 and GPIO.input(key) == 0:
            code.update({key:0})
    if len(clickedbuttons) == 4:
        print(clickedbuttons)
        if validcode == clickedbuttons:
            correct()
        else:
            if fail1 == False and fail2 == False:
                failed_one()
            elif fail1 == True and fail2 == False:
                failed_two()
            elif fail1 == True and fail2 == True:
                failed_three()
Citera
2022-11-20, 19:54
  #2
Moderator
Neksnors avatar
Kan inte python, men jag gissar att det ungefär handlar om att variabeln fail1 inte är global.
Så failed_one() deklarerar och vid behov modifierar en lokal (känd endast av funktionen) variabel med samma namn.
Sökordet scope kan vara användbart.
Citera
2022-11-20, 20:05
  #3
Medlem
I Python är inte variabler globala såsom i andra språk. Du deklarerar false1 igen och igen i varje funktion. Att den är med i "variabellistan" i övre delen bryr sig inte dina funktioner om.

Prova att skriva

Global false1
false1 = false

I din variabellista, då tror jag det kommer funka.

Obs! Det är bad practice att använda 'global'
Citera
2022-11-20, 20:08
  #4
Medlem
Citat:
Ursprungligen postat av PeggyOlson
I Python är inte variabler globala såsom i andra språk. Du deklarerar false1 igen och igen i varje funktion. Att den är med i "variabellistan" i övre delen bryr sig inte dina funktioner om.

Prova att skriva

Global false1
false1 = false

I din variabellista, då tror jag det kommer funka.

Obs! Det är bad practice att använda 'global'
Precis medlemsvariabler bör man undvika om det är möjligt
Citera
2022-11-20, 20:12
  #5
Medlem
Citat:
Ursprungligen postat av NilsHlt
Precis medlemsvariabler bör man undvika om det är möjligt

Det är det här beteendet som stör mig mest i Python. Har aldrig riktigt förstått hur man nyttjar detta på rätt sätt.
Citera
2022-11-20, 20:33
  #6
Medlem
Citat:
Ursprungligen postat av PeggyOlson
Det är det här beteendet som stör mig mest i Python. Har aldrig riktigt förstått hur man nyttjar detta på rätt sätt.

Du får använda argument och låta funktionerna returnera värden istället för att sätta globala variabler.

Finns en hel del att läsa på ämnet. https://www.baeldung.com/cs/global-variables

Citera
2022-11-20, 20:52
  #7
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av PeggyOlson
Det är det här beteendet som stör mig mest i Python. Har aldrig riktigt förstått hur man nyttjar detta på rätt sätt.
Varför stör det dig, du kan ju använda globala variabler med nyckelordet global? Globala variabler är oftast en dåligt idé, så det är bra att Python som default låter variabler vara lokala.
Citera
2022-11-20, 22:56
  #8
Medlem
Citat:
Ursprungligen postat av Enterprise
Varför stör det dig, du kan ju använda globala variabler med nyckelordet global? Globala variabler är oftast en dåligt idé, så det är bra att Python som default låter variabler vara lokala.

Det stör mig att jag kodar på det viset att jag vill använda globala variabler, precis så som TS gör.
Och dels är det ovant att variabeln x i en funktion plötsligt är ett annat objekt än det x jag skapat utanför funktionen, men bsra om jag tilldelar x något, jag kan fortfarande läsa x som skapats utanför.
Inga konstigheter egentligen, det är så det funkar. Men det är ovant.

Men jag (och TS) får dra nytta av detta och bli bättre programmera är helt enkelt.
Citera
2022-11-21, 07:49
  #9
Moderator
Protons avatar
Citat:
Ursprungligen postat av PeggyOlson
Det stör mig att jag kodar på det viset att jag vill använda globala variabler, precis så som TS gör.
Och dels är det ovant att variabeln x i en funktion plötsligt är ett annat objekt än det x jag skapat utanför funktionen, men bsra om jag tilldelar x något, jag kan fortfarande läsa x som skapats utanför.
Inga konstigheter egentligen, det är så det funkar. Men det är ovant.

Men jag (och TS) får dra nytta av detta och bli bättre programmera är helt enkelt.
Nu kan jag inte Python, men en sak är jag rätt säker på och det är att har man behov av globala variabler ligger det förmodligen en rejäl tankevurpa dold nån annanstans i koden.

Hade jag stött på en sån konstruktion hade jag försökt leta rätt på den globala variabeln (som i ett större sammanhang kan vara rejält knepig att hitta) och sedan skrivit om koden för att bli av med eländet.

Just när koden börjar växa är det för det första väldigt tidsödande att leta rätt på var variabeln deklarerats någonstans och för det andra kan det införa allvarliga buggar som kan vara rejält svåra att fixa, beroende på att variabeln kan sättas precis var som helst i koden och dessutom sättas i vilket state som helst i koden.
Citera
2022-11-21, 08:49
  #10
Medlem
HaveFuns avatar
Citat:
Ursprungligen postat av PeggyOlson
Det är det här beteendet som stör mig mest i Python. Har aldrig riktigt förstått hur man nyttjar detta på rätt sätt.
Du bakar in det i en class och sätter self.x = false

Sen när saker händer så uppdaterar du den.
Citera
2022-11-21, 09:01
  #11
Medlem
HaveFuns avatar
Citat:
Ursprungligen postat av Proton
Nu kan jag inte Python, men en sak är jag rätt säker på och det är att har man behov av globala variabler ligger det förmodligen en rejäl tankevurpa dold nån annanstans i koden.

Hade jag stött på en sån konstruktion hade jag försökt leta rätt på den globala variabeln (som i ett större sammanhang kan vara rejält knepig att hitta) och sedan skrivit om koden för att bli av med eländet.

Just när koden börjar växa är det för det första väldigt tidsödande att leta rätt på var variabeln deklarerats någonstans och för det andra kan det införa allvarliga buggar som kan vara rejält svåra att fixa, beroende på att variabeln kan sättas precis var som helst i koden och dessutom sättas i vilket state som helst i koden.

Det är korrekt. Rätt sätt är att använda klasser och sätt parametrar i klassen och uppdatera dessa. Och som du säger blir det väldigt svårt att felsöka senare, eller om man gjort något riktigt klantigt, omöjligt utan att bygga om allt från grunden.
Citera
2022-11-21, 12:37
  #12
Moderator
Pontiac-Garages avatar
Citat:
Ursprungligen postat av Proton
Nu kan jag inte Python, men en sak är jag rätt säker på och det är att har man behov av globala variabler ligger det förmodligen en rejäl tankevurpa dold nån annanstans i koden.

Hade jag stött på en sån konstruktion hade jag försökt leta rätt på den globala variabeln (som i ett större sammanhang kan vara rejält knepig att hitta) och sedan skrivit om koden för att bli av med eländet.

Just när koden börjar växa är det för det första väldigt tidsödande att leta rätt på var variabeln deklarerats någonstans och för det andra kan det införa allvarliga buggar som kan vara rejält svåra att fixa, beroende på att variabeln kan sättas precis var som helst i koden och dessutom sättas i vilket state som helst i koden.

Nja, ibland finns det ju behov av att använda globala variabler i Python då det är så pass by reference används i Python per automatik, då man inte kör med pointers.

Men absolut så bör (många) globala variabler undvikas då risken är stor att man får ett rörigt program med buggar i slutändan.
Citera
  • 1
  • 2

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback