How to switch value in Python

What is the most efficient way to switch between 0 and 1 ?

+101
python
Dec 05 '11 at 6:30
source share
17 answers

Solution using NOT

If the values ​​are Boolean, the fastest approach is to use the not operator:

 >>> x = True >>> x = not x # toggle >>> x False >>> x = not x # toggle >>> x True >>> x = not x # toggle >>> x False 

Subtraction Solution

If the values ​​are numeric, then subtracting from the sum is a simple and quick way to switch values:

 >>> A = 5 >>> B = 3 >>> total = A + B >>> x = A >>> x = total - x # toggle >>> x 3 >>> x = total - x # toggle >>> x 5 >>> x = total - x # toggle >>> x 3 

XOR Solution

If the value switches between 0 and 1, you can use a bitwise exclusive-or :

 >>> x = 1 >>> x ^= 1 >>> x 0 >>> x ^= 1 >>> x 1 

The technique generalizes to any pair of integers. The xor-by-one step is replaced by xor-by-precomputed-constant:

 >>> A = 205 >>> B = -117 >>> t = A ^ B # precomputed toggle constant >>> x = A >>> x ^= t # toggle >>> x -117 >>> x ^= t # toggle >>> x 205 >>> x ^= t # toggle >>> x -117 

(This idea was introduced by Nick Coglan and later summarized by @zxxc.)

Dictionary solution

If the values ​​are hashable, you can use a dictionary:

 >>> A = 'xyz' >>> B = 'pdq' >>> d = {A:B, B:A} >>> x = A >>> x = d[x] # toggle >>> x 'pdq' >>> x = d[x] # toggle >>> x 'xyz' >>> x = d[x] # toggle >>> x 'pdq' 

Conditional Expression Solution

The slowest way is to use a conditional expression :

 >>> A = [1,2,3] >>> B = [4,5,6] >>> x = A >>> x = B if x == A else A >>> x [4, 5, 6] >>> x = B if x == A else A >>> x [1, 2, 3] >>> x = B if x == A else A >>> x [4, 5, 6] 

Solution using itertools

If you have more than two values, the itertools.cycle () function provides a general quick way to switch between sequential values:

 >>> import itertools >>> toggle = itertools.cycle(['red', 'green', 'blue']).next >>> toggle() 'red' >>> toggle() 'green' >>> toggle() 'blue' >>> toggle() 'red' >>> toggle() 'green' >>> toggle() 'blue' 

Note that in Python 3, the next() method was changed to __next__() , so the first line will now be written as toggle = itertools.cycle(['red', 'green', 'blue']).__next__

+210
Dec 05 2018-11-12T00:
source share

I always use:

 p^=True 

If p is Boolean, it switches between true and false.

+27
May 10 '14 at 14:58
source share

Here is another unintuitive way. The beauty is that you can cycle through multiple values, not just two [0,1]

For two values ​​(switch)

 >>> x=[1,0] >>> toggle=x[toggle] 

For multiple values ​​(say 4)

 >>> x=[1,2,3,0] >>> toggle=x[toggle] 

I did not expect this decision to be almost the fastest.

 >>> stmt1=""" toggle=0 for i in xrange(0,100): toggle = 1 if toggle == 0 else 0 """ >>> stmt2=""" x=[1,0] toggle=0 for i in xrange(0,100): toggle=x[toggle] """ >>> t1=timeit.Timer(stmt=stmt1) >>> t2=timeit.Timer(stmt=stmt2) >>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000) 7.07 usec/pass >>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000) 6.19 usec/pass stmt3=""" toggle = False for i in xrange(0,100): toggle = (not toggle) & 1 """ >>> t3=timeit.Timer(stmt=stmt3) >>> print "%.2f usec/pass" % (1000000 * t3.timeit(number=100000)/100000) 9.84 usec/pass >>> stmt4=""" x=0 for i in xrange(0,100): x=x-1 """ >>> t4=timeit.Timer(stmt=stmt4) >>> print "%.2f usec/pass" % (1000000 * t4.timeit(number=100000)/100000) 6.32 usec/pass 
+22
Dec 05 '11 at 6:45
source share

The not operator negates your variable (turning it into a boolean if it is not already one). You can use 1 and 0 interchangeably with True and False , so just deny it:

 toggle = not toggle 

But if you use two arbitrary values, use the built-in if :

 toggle = 'a' if toggle == 'b' else 'b' 
+18
Dec 05 2018-11-12T00:
source share

Only between 1 and 0, do it

 1-x 

x can take 1 or 0

+13
Dec 05 2018-11-12T00:
source share

The trigonometric approach , simply because the sin and cos functions is cool.

enter image description here

 >>> import math >>> def generator01(): ... n=0 ... while True: ... yield abs( int( math.cos( n * 0.5 * math.pi ) ) ) ... n+=1 ... >>> g=generator01() >>> g.next() 1 >>> g.next() 0 >>> g.next() 1 >>> g.next() 0 
+8
Jul 18 '17 at 10:45
source share

Surprisingly, no one mentions the good old division modulo 2:

 In : x = (x + 1) % 2 ; x Out: 1 In : x = (x + 1) % 2 ; x Out: 0 In : x = (x + 1) % 2 ; x Out: 1 In : x = (x + 1) % 2 ; x Out: 0 

Note that this is equivalent to x = x - 1 , but the modulo advantage of the method is that the size of the group or the length of the interval can be more than just 2 elements, which gives you a similar pattern of cyclic alternation for iterating.

Now for only 2, the switch may be a little shorter (using a bit operator):

 x = x ^ 1 
+7
Jun 19 '13 at 11:52
source share

one way to switch is using multiple assignment

 >>> a = 5 >>> b = 3 >>> t = a, b = b, a >>> t[0] 3 >>> t = a, b = b, a >>> t[0] 5 

Using itertools:

 In [12]: foo = itertools.cycle([1, 2, 3]) In [13]: next(foo) Out[13]: 1 In [14]: next(foo) Out[14]: 2 In [15]: next(foo) Out[15]: 3 In [16]: next(foo) Out[16]: 1 In [17]: next(foo) Out[17]: 2 
+6
Jun 19 '13 at 11:18
source share

Using an Exception Handler

 >>> def toogle(x): ... try: ... return x/xx/x ... except ZeroDivisionError: ... return 1 ... >>> x=0 >>> x=toogle(x) >>> x 1 >>> x=toogle(x) >>> x 0 >>> x=toogle(x) >>> x 1 >>> x=toogle(x) >>> x 0 

Ok i'm the worst

enter image description here

 import math import sys d={1:0,0:1} l=[1,0] def exception_approach(x): try: return x/xx/x except ZeroDivisionError: return 1 def cosinus_approach(x): return abs( int( math.cos( x * 0.5 * math.pi ) ) ) def module_approach(x): return (x + 1) % 2 def subs_approach(x): return x - 1 def if_approach(x): return 0 if x == 1 else 1 def list_approach(x): global l return l[x] def dict_approach(x): global d return d[x] def xor_approach(x): return x^1 def not_approach(x): b=bool(x) p=not b return int(p) funcs=[ exception_approach, cosinus_approach, dict_approach, module_approach, subs_approach, if_approach, list_approach, xor_approach, not_approach ] f=funcs[int(sys.argv[1])] print "\n\n\n", f.func_name x=0 for _ in range(0,100000000): x=f(x) 
+4
Jul 18 '17 at 12:15
source share

The easiest way to switch between 1 and 0 is to subtract from 1.

 def toggle(value): return 1 - value 
+4
Aug 04 '17 at 6:46 on
source share

What about an imaginary switch that stores not only the current switch, but also a couple of other values ​​associated with it?

 toggle = complex.conjugate 

Save any + or - value to the left, and any unsigned value to the right:

 >>> x = 2 - 3j >>> toggle(x) (2+3j) 

Zero works too:

 >>> y = -2 - 0j >>> toggle(y) (-2+0j) 

It's easy to get the current switch value ( True and False represent + and -), LHS (real) value, or RHS (imaginary) value:

 >>> import math >>> curr = lambda i: math.atan2(i.imag, -abs(i.imag)) > 0 >>> lhs = lambda i: i.real >>> rhs = lambda i: abs(i.imag) >>> x = toggle(x) >>> curr(x) True >>> lhs(x) 2.0 >>> rhs(x) 3.0 

Easily swap LHS and RHS (but note that the sign of both values ​​should not be important):

 >>> swap = lambda i: i/-1j >>> swap(2+0j) 2j >>> swap(3+2j) (2+3j) 

Easily swap LHS and RHS, and switch simultaneously:

 >>> swaggle = lambda i: i/1j >>> swaggle(2+0j) -2j >>> swaggle(3+2j) (2-3j) 

Error protection:

 >>> toggle(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor 'conjugate' requires a 'complex' object but received a 'int' 

Make changes to LHS and RHS:

 >>> x += 1+2j >>> x (3+5j) 

... but be careful when manipulating RHS:

 >>> z = 1-1j >>> z += 2j >>> z (1+1j) # whoops! toggled it! 
+3
Jan 31 '19 at 23:19
source share

I use the abs function, very useful for loops

 x = 1 for y in range(0, 3): x = abs(x - 1) 

x will be 0.

+1
Oct 24 '17 at 17:15
source share

Rather, first ...

 def toggle(x = []): x.append('#') return len(x) % 2 
0
Jul 18 '17 at 17:49
source share

Let me make some hacking frames. Toggle a variable by name. Note: this may not work with every Python runtime.

Say you have an x ​​variable

 >>> import inspect >>> def toggle(var_name): >>> frame = inspect.currentframe().f_back >>> vars = frame.f_locals >>> vars[var_name] = 0 if vars[var_name] == 1 else 1 >>> x = 0 >>> toggle('x') >>> x 1 >>> toggle('x') >>> x 0 
0
Feb 01 '19 at 19:53
source share

If you are dealing with an integer variable, you can increase 1 and limit your set to 0 and 1 (mod)

 X = 0 # or X = 1 X = (X + 1)%2 
0
Feb 05 '19 at 22:04
source share

Variables a and b can have ANY two values, for example, 0 and 1, or 117 and 711, or “heads” and “tails”. No math is used, just a quick change of values ​​every time a switch is needed.

 a = True b = False a,b = b,a # a is now False a,b = b,a # a is now True 
0
Feb 06 '19 at 0:04
source share

Switching between -1 and +1 can be obtained using the built-in multiplication; used to calculate the Pi Leibniz number (or similar):

 sign = 1 result = 0 for i in range(100000): result += 1 / (2*i + 1) * sign sign *= -1 print("pi (estimate): ", result*4) 
0
Feb 06 '19 at 17:07
source share



All Articles