Jeg prøver å lage en funksjon som sammenligner flere variabler med et heltall og skriver ut en streng med tre bokstaver. Jeg lurte på om det finnes en måte å oversette dette til Python. La oss si:
x = 0
y = 1
z = 3
mylist = []
if x or y or z == 0 :
mylist.append("c")
if x or y or z == 1 :
mylist.append("d")
if x or y or z == 2 :
mylist.append("e")
if x or y or z == 3 :
mylist.append("f")
som ville returnere en liste over
["c", "d", "f"]
Er noe slikt mulig?
Du misforstår hvordan boolske uttrykk fungerer; de fungerer ikke som en engelsk setning og antar at du snakker om samme sammenligning for alle navn her. Du leter etter:
if x == 1 or y == 1 or z == 1:
x
og y
evalueres ellers hver for seg (False
hvis 0
, True
ellers).
Du kan forkorte dette ved å bruke en inneslutningstest mot a tuple:
if 1 in (x, y, z):
eller enda bedre:
if 1 in {x, y, z}:
ved å bruke a set
for å dra nytte av medlemskapstesten med konstant kostnad (in
tar en fast tid uansett hva den venstre operanden er).
Når du bruker or
, ser python hver side av operatøren som separate uttrykk. Uttrykket x eller y == 1
behandles først som en boolsk test for x
, og hvis det er False, testes uttrykket y == 1
.
Dette skyldes operatorenes forrang. Operatoren eller
har lavere prioritet enn ==
-testen, så sistnevnte evalueres først.
Men selv om dette ikke var tilfelle, og uttrykket x eller y eller z == 1
faktisk ble tolket som (x eller y eller z) == 1
i stedet, ville dette likevel ikke gjøre det du forventer.
x or y or z
ville bli evaluert til det første argumentet som er 'truthy', dvs. ikke False
, numerisk 0 eller tomt (se boolean expressions for detaljer om hva Python anser som false i en boolsk kontekst).
Så for verdiene x = 2; y = 1; z = 0
, vil x eller y eller z
løses opp til 2
, fordi det er den første true-lignende verdien i argumentene. Da vil 2 == 1
være False
, selv om y == 1
vil være True
.
Det samme vil gjelde for det omvendte; å teste flere verdier mot en enkelt variabel; x == 1 eller 2 eller 3
vil mislykkes av samme grunn. Bruk x == 1 eller x == 2 eller x == 3
eller x i {1, 2, 3}
.
Den direkte måten å skrive x eller y eller z == 0
på er
if any(map((lambda value: value == 0), (x,y,z))):
pass # write your logic.
Men jeg tror ikke du liker det :). Og denne måten er stygg.
Den andre måten (en bedre) er:
0 in (x, y, z)
Forresten, mange av hvis
ene kan skrives som noe slikt som dette
my_cases = {
0: Mylist.append("c"),
1: Mylist.append("d")
# ..
}
for key in my_cases:
if key in (x,y,z):
my_cases[key]()
break