web-dev-qa-db-de.com

So schalten Sie einen Wert in Python um

Was ist der effizienteste Weg, um zwischen 0 und 1 umzuschalten?

105
user1064306

Lösung mit NICHT

Wenn die Werte boolesch sind, verwenden Sie am besten den Operator not:

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

Lösung mit Abzug

Wenn die Werte numerisch sind, ist die Subtraktion von der Summe eine einfache und schnelle Möglichkeit, die Werte umzuschalten:

>>> 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

Lösung mit XOR

Wenn der Wert zwischen 0 und 1 wechselt, können Sie ein bitweises Exklusiv-Oder verwenden:

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

Die Technik verallgemeinert sich auf ein beliebiges Paar von Ganzzahlen. Die xor-by-one-Stufe wird durch eine xor-by-vorberechnete Konstante ersetzt:

>>> 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

(Diese Idee wurde von Nick Coghlan eingereicht und später von @zxxc verallgemeinert.)

Lösung mit einem Wörterbuch

Wenn die Werte hashierbar sind, können Sie ein Wörterbuch verwenden:

>>> 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'

Lösung mit einem bedingten Ausdruck

Der langsamste Weg ist die Verwendung eines bedingten Ausdrucks :

>>> 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]

Lösung mit itertools

Wenn Sie mehr als zwei Werte haben, bietet die Funktion itertools.cycle () eine generische schnelle Möglichkeit zum Wechseln zwischen aufeinanderfolgenden Werten:

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

Beachten Sie, dass in Python 3 die next()-Methode in __next__() geändert wurde. Die erste Zeile würde jetzt als toggle = itertools.cycle(['red', 'green', 'blue']).__next__ geschrieben.

223

Ich verwende immer:

p^=True

Wenn p ein boolescher Wert ist, wird zwischen wahr und falsch gewechselt.

27
renger

Hier ist ein anderer nicht intuitiver Weg. Das Schöne ist, Sie können mehrere Werte durchlaufen und nicht nur zwei [0,1]

Für zwei Werte (Umschalten)

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

Für mehrere Werte (etwa 4)

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

Ich habe nicht erwartet, dass diese Lösung auch fast die schnellste ist

>>> 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
Abhijit

Der Operator not negiert Ihre Variable (konvertiert sie in einen booleschen Wert, falls noch keine vorhanden ist). Sie können wahrscheinlich 1 und 0 austauschbar mit True und False verwenden, also negieren Sie es:

toggle = not toggle

Wenn Sie jedoch zwei beliebige Werte verwenden, verwenden Sie eine Inline if:

toggle = 'a' if toggle == 'b' else 'b'
18
Blender

Nur zwischen 1 und 0 tun Sie dies 

1-x 

x kann 1 oder 0 annehmen

14
M S

Trigonometrischer Ansatz, nur weil die Funktionen sin und cos cool sind.

 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
9
dani herrera

Überraschenderweise erwähnt niemand die gute alte 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

Beachten Sie, dass dies äquivalent zu x = x - 1 ist. Der Vorteil der Modulo-Technik besteht jedoch darin, dass die Größe der Gruppe oder die Länge des Intervalls größer als 2 Elemente sein kann, so dass Sie ein ähnliches Round-Robin-Interleaving-Schema zum Überlaufen erhalten.

Nur für 2 kann das Umschalten etwas kürzer sein (mit dem bitweisen Operator): 

x = x ^ 1
7

eine Möglichkeit zum Umschalten ist die Mehrfachzuweisung

>>> a = 5
>>> b = 3

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

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

Itertools verwenden:

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
hugo24

Die einfachste Möglichkeit, zwischen 1 und 0 umzuschalten, ist das Abziehen von 1.

def toggle(value):
    return 1 - value
4
Bunny Rabbit

Exception-Handler verwenden

>>> def toogle(x):
...     try:
...         return x/x-x/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, ich bin der schlimmste:

 enter image description here

import math
import sys

d={1:0,0:1}
l=[1,0]

def exception_approach(x):
    try:
        return x/x-x/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
dani herrera

Wie wäre es mit einem Imaginär Toggle, der nicht nur den aktuellen Toggle, sondern ein paar andere Werte speichert?

toggle = complex.conjugate

Speichern Sie einen beliebigen + oder - Wert links und jeden vorzeichenlosen Wert rechts: 

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

Null funktioniert auch:

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

Abrufen des aktuellen Umschaltwerts (True und False stehen für + und -), LHS-Wert (real) oder RHS-Wert (imaginärer Wert)

>>> 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

Tauschen Sie einfach LHS und RHS aus (beachten Sie jedoch, dass das Vorzeichen beider Werte nicht wichtig sein darf):

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

Tauschen Sie einfach LHS und RHS und gleichzeitig um:

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

Schutz vor Fehlern:

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

Änderungen an LHS und RHS vornehmen:

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

... aber seien Sie vorsichtig beim Manipulieren der RHS:

>>> z = 1-1j
>>> z += 2j
>>> z
(1+1j) # whoops! toggled it!
3
Rick Teachey

Ich verwende die abs-Funktion, sehr nützlich für Schleifen 

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

x wird 0 sein.

1
Proteo5

Die Variablen a und b können JEDE zwei Werte sein, wie 0 und 1 oder 117 und 711 oder "Köpfe" und "Schwänze". Es wird keine Mathematik verwendet, nur ein schneller Wechsel der Werte jedes Mal, wenn ein Toggle gewünscht wird.

a = True   
b = False   

a,b = b,a   # a is now False
a,b = b,a   # a is now True
1
user2948775

Lassen Sie uns ein paar Frame-Hacks machen. Variable nach Namen umschalten Hinweis: Dies funktioniert möglicherweise nicht bei jeder Python-Laufzeitumgebung.

Angenommen, Sie haben eine Variable "x"

>>> 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
Brantley Harris

Wenn Sie eine Integer-Variable verwenden, können Sie 1 erhöhen und Ihre Menge auf 0 und 1 beschränken (mod).

X = 0  # or X = 1
X = (X + 1)%2
0
Italo Nesi

Das Umschalten zwischen -1 und +1 kann durch Inline-Multiplikation erreicht werden. Wird zur Berechnung von Pi auf die Leibniz-Methode (oder ähnliches) verwendet:

sign = 1
result = 0
for i in range(100000):
    result += 1 / (2*i + 1) * sign
    sign *= -1
print("pi (estimate): ", result*4)
0
John Bograd