Pythons Äquivalent zu && (logisch-und) in einer if-Anweisung

830

Hier ist mein Code:

def front_back(a, b):
  # +++your code here+++
  if len(a) % 2 == 0 && len(b) % 2 == 0:
    return a[:(len(a)/2)] + b[:(len(b)/2)] + a[(len(a)/2):] + b[(len(b)/2):] 
  else:
    #todo! Not yet done. :P
  return

Ich erhalte einen Fehler in der IF- Bedingung.
Was mache ich falsch?

Arsen Khachaturyan
quelle
10
Natürlich wollte Sergio wissen, warum sein Code kaputt war, aber ich las etwas mehr in den Titel der Frage. Warum wäre && überhaupt nicht verfügbar? == und! = sind verfügbar (unterscheiden sich aber von ist und ist nicht, ich weiß). Warum nicht diese Syntax einschließen? Persönliche Präferenz?
Physikmichael
5
@ vgm64: Warum redundante Syntax einschließen, die keinen einzelnen Aspekt verbessert?
Konrad Rudolph
27
Es scheint mir, dass der Interpreter anstelle eines kryptischen "SyntaxError: ungültige Syntax" erkennen sollte, dass der Benutzer ihn verwendet hat, &&und ihm vorschlagen sollte, andstattdessen das Schlüsselwort zu verwenden. Gleiches gilt für Dinge wie ++und andere gängige Operatoren aus anderen Sprachen.
ArtOfWarfare
3
@physicsmichael "Es sollte einen und vorzugsweise nur einen offensichtlichen Weg geben, dies zu tun." import this
Nick T
3
@KonradRudolph Es verbessert absolut Aspekte der Sprache. Es ist konsistenter und intuitiver für alle, die jemals eine andere Sprache verwendet haben. Die Tatsache, dass diese Frage existiert und genauso viel Verkehr hat wie sie, unterstreicht dieses Problem deutlich als einen gemeinsamen Knackpunkt für die Menschen.
Zwischen

Antworten:

1473

Sie würden wollen , andstatt &&.

ChristopheD
quelle
2
Was soll ich dafür tun: wenn x == 'n' und y == 'a' oder y == 'b': <etwas tun> Wird es funktionieren? @ChristopheD
diffracteD
7
@diffracteD: Verwenden Sie Klammern, wenn Sie die Priorität von Standardoperatoren überschreiben möchten (Informationen dazu finden Sie hier: ibiblio.org/g2swap/byteofpython/read/operator-precedence.html )
ChristopheD
3
Ich mag , dass David Titarenco gab einen Ausschnitt-n-Paste Beispiel
Alexx Roche
7
Ich bin hier angekommen, nachdem ich beide eingegeben habe &&und ANDeine Fehlermeldung erhalten habe ( ich habe nicht erwartet, dass Python das Kleinbuchstaben möchte and).
Xeoncross
2
Ich denke, Sie sollten & See verwenden: stackoverflow.com/questions/36921951/…
user1761806
229

Python verwendet andund orBedingungen.

dh

if foo == 'abc' and bar == 'bac' or zoo == '123':
  # do something
David Titarenco
quelle
5
Vergessen Sie nicht, dass Python auch nicht hat (
inspectorG4dget
9
Wird Ihr Beispiel mit "(wenn dies und das) oder" ODER "wenn dies und (dies oder das)" bewertet?
Jeff
12
@ Jeff Dein erster Weg. and hat eine höhere Priorität als or.
Buge
1
@Buge es sieht so aus, als ob "oder" weiter oben in der Tabelle steht, die Sie verlinkt haben
Matt
5
@Matt die Tabelle wechselt von der niedrigsten zur höchsten Priorität. Es ist einfacher, sich an den Vorrang zu erinnern, wenn Sie die Boolesche Algebra studiert haben. "oder" ist Addition und "und" ist Multiplikation.
Michael Stroud
48

Ich erhalte einen Fehler in der IF-Bedingung. Was mache ich falsch?

Der Grund dafür SyntaxErrorist, dass es &&in Python keinen Operator gibt . Ebenso ||und !sind keine gültigen Python-Operatoren.

Einige der Operatoren, die Sie möglicherweise aus anderen Sprachen kennen, haben in Python einen anderen Namen. Die logischen Operatoren &&und ||werden tatsächlich andund genannt or. Ebenso wird der logische Negationsoperator !aufgerufen not.

Sie könnten also einfach schreiben:

if len(a) % 2 == 0 and len(b) % 2 == 0:

oder auch:

if not (len(a) % 2 or len(b) % 2):

Einige zusätzliche Informationen (die nützlich sein könnten):

Ich habe die Operator "Äquivalente" in dieser Tabelle zusammengefasst:

+------------------------------+---------------------+
|  Operator (other languages)  |  Operator (Python)  |
+==============================+=====================+
|              &&              |         and         |
+------------------------------+---------------------+
|              ||              |         or          |
+------------------------------+---------------------+
|              !               |         not         |
+------------------------------+---------------------+

Siehe auch Python-Dokumentation: 6.11. Boolesche Operationen .

Neben den logischen Operatoren hat Python auch bitweise / binäre Operatoren:

+--------------------+--------------------+
|  Logical operator  |  Bitwise operator  |
+====================+====================+
|        and         |         &          |
+--------------------+--------------------+
|         or         |         |          |
+--------------------+--------------------+

In Python gibt es keine bitweise Negation (nur den bitweisen inversen Operator ~- aber das entspricht nichtnot ).

Siehe auch 6.6. Unäre arithmetische und bitweise / binäre Operationen und 6.7. Binäre Rechenoperationen .

Die logischen Operatoren (wie in vielen anderen Sprachen) haben den Vorteil, dass diese kurzgeschlossen sind. Das heißt, wenn der erste Operand das Ergebnis bereits definiert, wird der zweite Operator überhaupt nicht ausgewertet.

Um dies zu zeigen, verwende ich eine Funktion, die einfach einen Wert nimmt, ihn druckt und wieder zurückgibt. Dies ist praktisch, um zu sehen, was aufgrund der print-Anweisungen tatsächlich ausgewertet wird:

>>> def print_and_return(value):
...     print(value)
...     return value

>>> res = print_and_return(False) and print_and_return(True)
False

Wie Sie sehen, wird nur eine print-Anweisung ausgeführt, sodass Python nicht einmal den richtigen Operanden angesehen hat.

Dies ist bei den Binäroperatoren nicht der Fall. Diese bewerten immer beide Operanden:

>>> res = print_and_return(False) & print_and_return(True);
False
True

Aber wenn der erste Operand nicht ausreicht, wird natürlich der zweite Operator ausgewertet:

>>> res = print_and_return(True) and print_and_return(False);
True
False

Um dies hier zusammenzufassen, ist eine andere Tabelle:

+-----------------+-------------------------+
|   Expression    |  Right side evaluated?  |
+=================+=========================+
| `True` and ...  |           Yes           |
+-----------------+-------------------------+
| `False` and ... |           No            |
+-----------------+-------------------------+
|  `True` or ...  |           No            |
+-----------------+-------------------------+
| `False` or ...  |           Yes           |
+-----------------+-------------------------+

Die Trueund Falsestellen dar, was bool(left-hand-side)zurückkehrt, sie müssen nicht sein Trueoder Falsesie müssen nur zurückkehren Trueoder Falsewann sie boolaufgerufen werden (1).

In Pseudo-Code (!) Funktionieren die Funktionen andund orwie folgt:

def and(expr1, expr2):
    left = evaluate(expr1)
    if bool(left):
        return evaluate(expr2)
    else:
        return left

def or(expr1, expr2):
    left = evaluate(expr1)
    if bool(left):
        return left
    else:
        return evaluate(expr2)

Beachten Sie, dass dies Pseudocode und kein Python-Code ist. In Python können Sie keine Funktionen erstellen, die aufgerufen werden andoder orweil dies Schlüsselwörter sind. Auch sollten Sie niemals "evaluieren" oder verwenden if bool(...).

Anpassen des Verhaltens Ihrer eigenen Klassen

Diese implizite boolAufruf kann verwendet werden , um anzupassen , wie Ihre Klassen verhalten sich mit and, orund not.

Um zu zeigen, wie dies angepasst werden kann, verwende ich diese Klasse, die wiederum printetwas ist, um zu verfolgen, was passiert:

class Test(object):
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        print('__bool__ called on {!r}'.format(self))
        return bool(self.value)

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return "{self.__class__.__name__}({self.value})".format(self=self)

Mal sehen, was mit dieser Klasse in Kombination mit diesen Operatoren passiert:

>>> if Test(True) and Test(False):
...     pass
__bool__ called on Test(True)
__bool__ called on Test(False)

>>> if Test(False) or Test(False):
...     pass
__bool__ called on Test(False)
__bool__ called on Test(False)

>>> if not Test(True):
...     pass
__bool__ called on Test(True)

Wenn Sie keine __bool__Methode haben, prüft Python auch, ob das Objekt eine __len__Methode hat und ob es einen Wert größer als Null zurückgibt. Dies kann hilfreich sein, wenn Sie einen Sequenzcontainer erstellen.

Siehe auch 4.1. Wahrheitswertprüfung .

NumPy-Arrays und Unterklassen

Wahrscheinlich etwas außerhalb des Rahmens der ursprünglichen Frage, aber falls Sie mit NumPy-Arrays oder -Unterklassen (wie Pandas Series oder DataFrames) arbeiten, wird der implizite boolAufruf die gefürchteten ValueError:

>>> import numpy as np
>>> arr = np.array([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> import pandas as pd
>>> s = pd.Series([1,2,3])
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> s and s
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

In diesen Fällen können Sie die Logik und Funktion von NumPy verwenden, die elementweise and(oder or) ausführt :

>>> np.logical_and(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([False, False,  True, False])
>>> np.logical_or(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([ True, False,  True,  True])

Wenn Sie nur mit booleschen Arrays arbeiten, können Sie auch die Binäroperatoren mit NumPy verwenden. Diese führen elementweise (aber auch binäre) Vergleiche durch:

>>> np.array([False,False,True,True]) & np.array([True, False, True, False])
array([False, False,  True, False])
>>> np.array([False,False,True,True]) | np.array([True, False, True, False])
array([ True, False,  True,  True])

(1)

Dass der boolAufruf der Operanden zurückkehren muss Trueoder Falsenicht ganz korrekt ist. Es ist nur der erste Operand, der in seiner __bool__Methode einen Booleschen Wert zurückgeben muss :

class Test(object):
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        return self.value

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return "{self.__class__.__name__}({self.value})".format(self=self)

>>> x = Test(10) and Test(10)
TypeError: __bool__ should return bool, returned int
>>> x1 = Test(True) and Test(10)
>>> x2 = Test(False) and Test(10)

Das ist , weil andtatsächlich den ersten Operanden zurückgibt , wenn der erste Operand ausgewertet Falseund , wenn sie ausgewertet Truedann gibt er den zweiten Operanden:

>>> x1
Test(10)
>>> x2
Test(False)

Ähnliches gilt für, oraber umgekehrt:

>>> Test(True) or Test(10)
Test(True)
>>> Test(False) or Test(10)
Test(10)

Wenn Sie sie jedoch in einer ifAnweisung verwenden, ifruft booldas Ergebnis implizit auch das Ergebnis auf. Daher sind diese Feinheiten für Sie möglicherweise nicht relevant.

MSeifert
quelle
36

Zwei Kommentare:

  • Verwenden Sie andund orfür logische Operationen in Python.
  • Verwenden Sie 4 Leerzeichen zum Einrücken anstelle von 2. Sie werden sich später bedanken, da Ihr Code fast genauso aussieht wie der Code aller anderen. Siehe PEP 8 für weitere Details.
istruble
quelle
10

Sie verwenden andundor führen logische Operationen wie in C, C ++ aus. Wie buchstäblich andist &&und orist|| .


Schauen Sie sich dieses lustige Beispiel an:

Angenommen, Sie möchten Logic Gates in Python erstellen:

def AND(a,b):
    return (a and b) #using and operator

def OR(a,b):
    return (a or b)  #using or operator

Rufen Sie sie jetzt an:

print AND(False, False)
print OR(True, False)

Dies wird Folgendes ausgeben:

False
True

Hoffe das hilft!

geekidharsh
quelle
9

Ich habe mich für eine rein mathematische Lösung entschieden:

def front_back(a, b):
  return a[:(len(a)+1)//2]+b[:(len(b)+1)//2]+a[(len(a)+1)//2:]+b[(len(b)+1)//2:]
Groß Rot
quelle
7
Dies ist keine Antwort auf die eigentliche Frage.
Matthew Read
5

Wahrscheinlich ist dies nicht der beste Code für diese Aufgabe, aber er funktioniert -

def front_back(a, b):

 if len(a) % 2 == 0 and len(b) % 2 == 0:
    print a[:(len(a)/2)] + b[:(len(b)/2)] + a[(len(a)/2):] + b[(len(b)/2):]

 elif len(a) % 2 == 1 and len(b) % 2 == 0:
    print a[:(len(a)/2)+1] + b[:(len(b)/2)] + a[(len(a)/2)+1:] + b[(len(b)/2):] 

 elif len(a) % 2 == 0 and len(b) % 2 == 1:
     print a[:(len(a)/2)] + b[:(len(b)/2)+1] + a[(len(a)/2):] + b[(len(b)/2)+1:] 

 else :
     print a[:(len(a)/2)+1] + b[:(len(b)/2)+1] + a[(len(a)/2)+1:] + b[(len(b)/2)+1:]
Nasimuddin Ansari
quelle
-3

Ein einzelnes &(nicht doppeltes &&) ist genug oder wie die obere Antwort andeutet, können Sie 'und' verwenden. Ich fand das auch bei Pandas

cities['Is wide and has saint name'] = (cities['Population'] > 1000000) 
& cities['City name'].apply(lambda name: name.startswith('San'))

Wenn wir das "&" durch "und" ersetzen, funktioniert es nicht.

William You
quelle
1
Single &
schließt
-4

Vielleicht ist mit & stattdessen% schneller und besser lesbar

andere Tests gerade / ungerade

x ist gerade? x% 2 == 0

x ist ungerade? nicht x% 2 == 0

vielleicht ist mit bitwise und 1 klarer

x ist ungerade? x & 1

x ist gerade? nicht x & 1 (nicht ungerade)

def front_back(a, b):
    # +++your code here+++
    if not len(a) & 1 and not len(b) & 1:
        return a[:(len(a)/2)] + b[:(len(b)/2)] + a[(len(a)/2):] + b[(len(b)/2):] 
    else:
        #todo! Not yet done. :P
    return
Wirefall
quelle
-4

Verwendung von "und" unter bestimmten Bedingungen. Ich benutze dies oft beim Importieren in Jupyter Notebook:

def find_local_py_scripts():
    import os # does not cost if already imported
    for entry in os.scandir('.'):
        # find files ending with .py
        if entry.is_file() and entry.name.endswith(".py") :
            print("- ", entry.name)
find_local_py_scripts()

-  googlenet_custom_layers.py
-  GoogLeNet_Inception_v1.py
Uki D. Lucas
quelle
14
Diese Frage wurde vor fast 7 Jahren gestellt und beantwortet. Was fügt Ihre Antwort zu den Antworten hinzu, die bereits hier sind? Im Allgemeinen sollten Sie einer alten Frage, bei der das Alter als mehrere Jahre gemessen wird, keine neue Antwort hinzufügen, es sei denn, Sie haben etwas überraschend Neues zu sagen, wenn bereits gute Antworten verfügbar sind.
Jonathan Leffler