views:

352

answers:

6

In some part of my Python program I have a val variable that can be 1 or 0. If it's 1 I must change to 0, if it's 0 I must change to 1.

How do you do it in a Pythonic way?

if val == 1:
    val = 0
elif val == 0:
    val = 1

it's too long!

I did:

swap = {0: 1, 1:0}

So I can use it:

swap[val]

Other ideas?

+22  A: 

This isn't pythonic, but it is language neutral. Often val = 1 - val is simplest.

Charles Bailey
That's too readable! Go for `val ^= 1` !
abyx
That is clever, but it requires the person reading your code to think (probably), which may force you to have add a comment. I like the ternary better eg. val = 0 if val else 1 because it says exactly what it does.
rplevy
MAK
I guess I would just create a method called `bit_flip` and use the code in this answer. Once the name is there, it should be pretty easy to pick up what it does.
abyx
`val = 1 - val` in no way communicates `val` is always either `1` or `0` and that it is supposed to *swap/flip* these values. `marked = not marked` communicates both.
J.F. Sebastian
@J.F. Sebastien: The original poster didn't say why, but seemed to want a number and not a boolean so you'd have to do `int(not val)` to get _exactly_ the same behaviour. I think that this was discussed on the comments to one of the other answers.
Charles Bailey
+10  A: 

Since True == 1 and False == 0 in python,

you could just use var = not var

It will just swap it.

S.Mark
not 1 == False, not 0 == True
Ken Bloom
This seems an implementation detail and can't rely on it.
Juanjo Conti
but `int(not 1) == 0` and `int(not 0) == 1` because `int(True) == 1` and `int(False) == 0`. and this one is likely not an implementation detail.
Adrien Plisson
bool is a subclass of int, and Alex Martelli uses `sum([list of booleans]` to count the number of True's, so I think it must be safe.
unutbu
The fact that 0 evalutes to false, and 1 to true in a boolean context are both guaranteed in python: http://docs.python.org/reference/expressions.html#boolean-operations
Charles Bailey
seems like telling `var = not var` is like `parsing html with regex` in SO? I can't believe that!
S.Mark
It's safe (and just fine!) if all you ever do with `var` is arithmetic (nothing to do with "parsing html with regex", which is just silly!-), but if you ever do a `str(var)` (including an intrinsic one e.g. in `print`), bool behaves differently (as a subclass, it overrides `__str__`). Not enough info in the question to make sure there's no such stringification, so `1 - var` as in the selected answer is safer.
Alex Martelli
It's safe but not expressive as prose, which is why i would suggest using the ternary (see my answer).
rplevy
+1  A: 

If you want to be short:

f = lambda val: 0 if val else 1

Then:

>>> f(0)
1
>>> f(1)
0
Loïc Wolff
+1  A: 

In your case I recommend the ternary:

val = 0 if val else 1

If you had 2 variables to swap you could say:

(a, b) = (b, a)
rplevy
OP doesn't have two values to swap. he has a single value that he wants to change
SilentGhost
Added an edit. Ternary makes more sense here.
rplevy
+5  A: 

Just another possibility:

i = (1,0)[i]

The advantage is that it generates an error if i is anything else than 0 or 1.

Are you sure you don't want to use False and True? It sounds almost like it.

Georg
+2  A: 

The shortest is the bitwise operator XOR:

val ^= 1
enrnpfnfp