Python: Varför funkar inte mitt if statement med or här?

Permalänk

Python: Varför funkar inte mitt if statement med or här?

Är nybörjare med att programmera Python. Håller på med en regelbaserad chatbot för Telegram som funkar fint, dock inte när jag försöker stapla flera alternativ såhär

if "hej" or "hallå" or "tjena" in user_message: time.sleep(2) return random.choice(Hälsningar)

Vad är det som jag missförstår och hur kan jag göra så det fungerar på rätt sätt?

Tydliggjort med kod-formatering
Permalänk
Medlem

Du får nog göra "in"-kollen separat för varje sträng.

if "hej" in user_message or "tjena" in user_message osv

Visa signatur

i5-7600k . GTX 1080 . 16 GB

Permalänk
Avstängd

Typ så här:

if 'a' in ['a','f','g'] or 'b' in ['a','f','g'] or 'c' in ['a','f','g']: print ("yep")

Permalänk
Medlem

Du kan använda expressions om du vill. Jag är också nybörjare på python, men tror att det här är lättare kod att använda.

words = {'hej', 'hallå', 'tjena'} message = "Hej, hur mår du?" has_word = any(word.casefold() in message.casefold() for word in words) print(has_word)

Permalänk
Medlem

Problemet är alltså att in har högre prioritet än or, så ditt villkor tolkas som:

("hej") or ("hallå") or ("tjena" in user_message)

Eftersom strängar i python anses vara "sanna" om de ej är tomma så är detta ekvivalent med:

True or True or ("tjena" in user_message)

vilket förstås alltid är sant.

Permalänk
Skrivet av johanandersson:

Du får nog göra "in"-kollen separat för varje sträng.

if "hej" in user_message or "tjena" in user_message osv

Det funkade! 🙂

Permalänk
Skrivet av stgr:

Typ så här:

if 'a' in ['a','f','g'] or 'b' in ['a','f','g'] or 'c' in ['a','f','g']: print ("yep")

Ok! Jag förstår inte riktigt hur jag översätter det till min kod bara?

Permalänk
Skrivet av patrik80:

Du kan använda expressions om du vill. Jag är också nybörjare på python, men tror att det här är lättare kod att använda.

words = {'hej', 'hallå', 'tjena'} message = "Hej, hur mår du?" has_word = any(word.casefold() in message.casefold() for word in words) print(has_word)

Tack! Detta är lite för svårt för mig än. Förstår knappt koden 😂

Permalänk
Skrivet av perost:

Problemet är alltså att in har högre prioritet än or, så ditt villkor tolkas som:

("hej") or ("hallå") or ("tjena" in user_message)

Eftersom strängar i python anses vara "sanna" om de ej är tomma så är detta ekvivalent med:

True or True or ("tjena" in user_message)

vilket förstås alltid är sant.

Tack för att du förklarade det!

Permalänk
Medlem
Skrivet av joachim_s:

Tack! Detta är lite för svårt för mig än. Förstår knappt koden 😂

Är det nåt specifikt i koden du inte förstår? Även om expressions kanske inte är det första man lär sig så är det ju hyfsat enkel Python.

Permalänk
Medlem

Använd re.match istället, lättare och snabbare.

import re regex = re.compile('^(hej|tjena|hall\w)') if regex.match(user_message): time.sleep(2) return random.choice(Hälsningar)

Visa signatur

AMD 7800X3D | ASUS TUF X670E-PLUS | Corsair Vengeance DDR5 32GB EXPO | ASUS TUF 4090 OC 24GB |
Noctua NH-U12A | Corsair 4000D | Corsair AX1200W | Steelseries Apex 7 | Steelseries Sensei Ten | ASUS VG35VQ

https://github.com/Mariusz89B

Permalänk
99:e percentilen
Skrivet av M89:

Använd re.match istället, lättare och snabbare.

import re regex = re.compile('^(hej|tjena|hall\w)') if regex.match(user_message): time.sleep(2) return random.choice(Hälsningar)

Men betyder inte alls samma sak.

>>> bool(re.compile('^(hej|tjena|hall\w)').match("ja hej du")) False >>> "hej" in "ja hej du" True

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem
Skrivet av M89:

Använd re.match istället, lättare och snabbare.

Grattis, nu har du två problem.

Permalänk
Medlem
Skrivet av Alling:

Men betyder inte alls samma sak.

>>> bool(re.compile('^(hej|tjena|hall\w)').match("ja hej du")) False >>> "hej" in "ja hej du" True

Var bara ett exempel. Ser nu att det skulle vara "in" då får det bli så här istället:

>>> bool(re.compile('(hej|tjena|hall\w)').findall("ja hej du")) True

Visa signatur

AMD 7800X3D | ASUS TUF X670E-PLUS | Corsair Vengeance DDR5 32GB EXPO | ASUS TUF 4090 OC 24GB |
Noctua NH-U12A | Corsair 4000D | Corsair AX1200W | Steelseries Apex 7 | Steelseries Sensei Ten | ASUS VG35VQ

https://github.com/Mariusz89B

Permalänk
99:e percentilen
Skrivet av M89:

Var bara ett exempel. Ser nu att det skulle vara "in" då får det bli så här istället:

>>> bool(re.compile('[^.*](hej|tjena|hall\w)').match("ja hej du")) True

I så fall med search istället för att krångla med [^.*]:

>>> bool(re.compile('(hej|tjena|hall\w)').search("ja hej du")) True

Men det betyder fortfarande inte samma sak:

>>> bool(re.compile('(hej|tjena|hall\w)').search("halloj")) True >>> "hallå" in "halloj" False

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem
Skrivet av Alling:

I så fall med search istället för att krångla med ^.*:

>>> bool(re.compile('(hej|tjena|hall\w)').search("ja hej du")) True

Men det betyder fortfarande inte samma sak:

>>> bool(re.compile('(hej|tjena|hall\w)').search("halloj")) True >>> "hallå" in "halloj" False

Jag var lite för snabb, har redigerat mitt senaste inlägg. Search eller findall går att använda.

Lite osäker på svenska bokstäver, men kanske går att använda å i regex.

bool(re.compile('(hej|tjena|hallå)').findall("ja du halloj"))

Visa signatur

AMD 7800X3D | ASUS TUF X670E-PLUS | Corsair Vengeance DDR5 32GB EXPO | ASUS TUF 4090 OC 24GB |
Noctua NH-U12A | Corsair 4000D | Corsair AX1200W | Steelseries Apex 7 | Steelseries Sensei Ten | ASUS VG35VQ

https://github.com/Mariusz89B

Permalänk
99:e percentilen
Skrivet av M89:

>>> bool(re.compile('(hej|tjena|hall\w)').findall("ja hej du")) True

Skrivet av M89:

Jag var lite för snabb, har redigerat mitt senaste inlägg. Search eller findall går att använda.

Betyder ändå inte samma sak:

>>> bool(re.compile('(hej|tjena|hall\w)').findall("halloj")) True >>> "hallå" in "halloj" False

Jag har ingenting emot regex, men någon som vill skulle möjligen kunna argumentera för att det kanske inte alls var lättare att använda regex i det här fallet.

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem
Skrivet av Alling:

Betyder ändå inte samma sak:

>>> bool(re.compile('(hej|tjena|hall\w)').findall("halloj")) True >>> "hallå" in "halloj" False

Jag har ingenting emot regex, men någon som vill skulle möjligen kunna argumentera för att det kanske inte alls var lättare att använda regex i det här fallet.

Lite osäker på svenska bokstäver, men kanske går att använda å i regex.

bool(re.compile('(hej|tjena|hallå)').findall("ja du halloj"))

Jag ger dig det att du har rätt ang. lättare, det är dock snabbare när du ska iterera många ord.

Visa signatur

AMD 7800X3D | ASUS TUF X670E-PLUS | Corsair Vengeance DDR5 32GB EXPO | ASUS TUF 4090 OC 24GB |
Noctua NH-U12A | Corsair 4000D | Corsair AX1200W | Steelseries Apex 7 | Steelseries Sensei Ten | ASUS VG35VQ

https://github.com/Mariusz89B

Permalänk
99:e percentilen
Skrivet av M89:

Lite osäker på svenska bokstäver, men kanske går att använda å i regex.

bool(re.compile('(hej|tjena|hallå)').findall("ja du halloj"))

Möjligt att du har rätt ang. lättare, det är dock snabbare när du ska iterera många ord.

Ja, det kan mycket väl vara så att regex är den bättre lösningen på TS egentliga problem. Min poäng var framförallt att uppmuntra till noggrannhet när man föreslår en påstått ekvivalent lösning.

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
99:e percentilen
Skrivet av perost:

Problemet är alltså att in har högre prioritet än or, så ditt villkor tolkas som:

("hej") or ("hallå") or ("tjena" in user_message)

Eftersom strängar i python anses vara "sanna" om de ej är tomma så är detta ekvivalent med:

True or True or ("tjena" in user_message)

vilket förstås alltid är sant.

Jättebra förklaring! Värt att tillägga är att om or istället hade haft högre prioritet än in hade villkoret tolkats som

("hej" or "hallå" or "tjena") in user_message

vilket är ekvivalent med

"hej" in user_message

eftersom ("hej" or "hallå" or "tjena") == "hej".

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem
Skrivet av johanandersson:

Du får nog göra "in"-kollen separat för varje sträng.

if "hej" in user_message or "tjena" in user_message osv

Japp, helt klart det enklaste och tydligaste för en nybörjare, någon optimering behövs ju inte i detta fall.

Ett tips om if-satserna börjar bli svårlästa är att först tilldela jämförelseresultaten (true/false) till tydliga variabelnamn. Inte det mest optimala exemplet, men du kanske förstår vad jag menar:

user_message = "men hallå där" contains_hej = "hej" in user_message contains_halla = "hallå" in user_message contains_tjena = "tjena" in user_message if contains_hej or contains_halla or contains_tjena: print("Hejsan")

Observera att detta exempel inte är optimalt då alla textjämförelser nu alltid kommer att köras och dessutom tilldelas till variabler, men beroende på vad man utvecklar och optimeringsbehov kan det ibland vara en bra idé att först göra mer lättläst kod som är enklare att debugga, snarare än att göra svårläst men mer optimerad kod.

Man får helt enkelt tänka efter lite, är det rader som skall köras tusentals gånger per sekund så kan det ju vara värt att optimera, beroende på vad det handlar om.