Odpowiednik && (logiczny-i) w Pythonie w instrukcji if


828

Oto mój kod:

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

Dostaję błąd w warunkowym IF .
Co ja robię źle?


10
Najwyraźniej Sergio chciał wiedzieć, dlaczego jego kod został złamany, ale przeczytałem nieco więcej w tytule pytania. Dlaczego i & i tak nie byłyby dostępne? == i! = są dostępne (ale różnią się od jest i nie jest, wiem). Dlaczego nie dołączyć tej składni? Osobiste preferencje?
physicsmichael

5
@ vgm64: Dlaczego warto stosować składnię nadmiarową, która nie poprawia ani jednego aspektu?
Konrad Rudolph

27
Wydaje mi się, że interpreter powinien zamiast drukować tajemnicze „Błąd składni: nieprawidłowa składnia” - wykryj, że użytkownik go użył &&i zasugeruj, że może andzamiast tego użyć słowa kluczowego . To samo dotyczy rzeczy takich jak ++i innych popularnych operatorów z innych języków.
ArtOfWarfare

3
@physicsmichael „powinien istnieć jeden, a najlepiej tylko jeden, oczywisty sposób na zrobienie tego”. import this
Nick T

3
@KonradRudolph To absolutnie poprawia aspekty języka. Jest bardziej spójny i intuicyjny dla każdego, kto kiedykolwiek używał innego języka. fakt, że pytanie to istnieje i ma tyle samo ruchu, co wyraźnie uwypukla tę kwestię jako wspólny punkt zaczepienia dla ludzi.
jterm

Odpowiedzi:


1469

Wolałbyś andzamiast &&.


2
co mam z tym zrobić: jeśli x == 'n' iy == 'a' lub y == 'b': <zrób coś> Czy to zadziała!? @ChristopheD
diffracteD

7
@diffracteD: Użyj nawiasów, jeśli chcesz zastąpić standardowe pierwszeństwo operatorów (o którym możesz się dowiedzieć tutaj: ibiblio.org/g2swap/byteofpython/read/operator-precedence.html )
ChristopheD

3
Podoba mi się, że David Titarenco podał przykład „
Alexx Roche

7
Przybyłem tutaj po wpisaniu obu &&i ANDdostałem błąd (nie oczekuję, że python będzie chciał napisać małe litery and).
Xeoncross,

2
Myślę, że powinieneś użyć & See: stackoverflow.com/questions/36921951/…
user1761806

229

Zastosowania andi orwarunki warunkowe w Pythonie .

to znaczy

if foo == 'abc' and bar == 'bac' or zoo == '123':
  # do something

5
Nie zapominaj, że python również nie ma (no i!)
inspectorG4dget

9
Czy twój przykład ocenia na „(jeśli to i to) lub tamto„ LUB ”, jeśli to i (to lub tamto)”?
Jeff

12
@Jeff Twój pierwszy sposób. and ma wyższy priorytet niż or.
Buge

1
@Buge wygląda na to, że „lub” znajduje się wyżej w tabeli, którą połączyłeś
Matt

5
@Matt tabela przechodzi od najniższego priorytetu do najwyższego. Łatwiej zapamiętać pierwszeństwo, jeśli studiowałeś algebrę boolowską; „lub” to dodawanie, a „a” to mnożenie.
Michael Stroud,

48

Dostaję błąd w warunkowym IF. Co ja robię źle?

Istnieje powód, dla którego dostajesz SyntaxErrorto, że &&w Pythonie nie ma operatora. Podobnie ||i nie!poprawnymi operatorami języka Python.

Niektóre operatory, które możesz znać z innych języków, mają w Pythonie inną nazwę. Operatory logiczne &&i ||faktycznie są nazywane andi or. Podobnie !wywoływany jest operator logicznej negacji not.

Więc możesz po prostu napisać:

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

lub nawet:

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

Kilka dodatkowych informacji (które mogą się przydać):

Podsumowałem operatora „ekwiwalenty” w tej tabeli:

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

Zobacz także dokumentację Pythona: 6.11. Operacje logiczne .

Oprócz operatorów logicznych Python ma także operatory bitowe / binarne:

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

W Pythonie nie ma bitowej negacji (tylko bitowy operator odwrotny ~- ale to nie jest równoważne not).

Zobacz także 6.6. Jednoargumentowe operacje arytmetyczne i bitowe / binarne oraz 6.7. Binarne operacje arytmetyczne .

Operatory logiczne (podobnie jak w wielu innych językach) mają tę zaletę, że są zwarte. Oznacza to, że jeśli pierwszy argument już określa wynik, to drugi operator nie jest w ogóle oceniany.

Aby to pokazać, używam funkcji, która po prostu przyjmuje wartość, drukuje ją i zwraca ponownie. Jest to przydatne, aby zobaczyć, co jest faktycznie oceniane na podstawie instrukcji print:

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

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

Jak widać, wykonywana jest tylko jedna instrukcja print, więc Python tak naprawdę nawet nie spojrzał na odpowiedni operand.

Nie dotyczy to operatorów binarnych. Zawsze oceniają oba operandy:

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

Ale jeśli pierwszy operand nie wystarczy, wówczas oceniany jest drugi operator:

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

Podsumowując, oto kolejna tabela:

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

TrueI Falsereprezentują co bool(left-hand-side)powraca, nie trzeba być Truealbo False, po prostu trzeba zwrócić Truelub Falsegdy boolnazywa się na nich (1).

Tak więc w Pseudokodzie (!) Funkcje andi ordziałają w następujący sposób:

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)

Zauważ, że to pseudo-kod, a nie kod Pythona. W Pythonie nie można tworzyć wywoływanych funkcji andlub orponieważ są to słowa kluczowe. Nigdy też nie powinieneś używać „oceny” lub if bool(...).

Dostosowywanie zachowania własnych klas

To niejawne boolwywołanie może być użyte do dostosowania sposobu, w jaki zachowują się twoje klasy and, ororaz not.

Aby pokazać, jak można to dostosować, używam tej klasy, która ponownie printjest czymś, co pozwala śledzić, co się dzieje:

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)

Zobaczmy więc, co dzieje się z tą klasą w połączeniu z tymi operatorami:

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

Jeśli nie masz __bool__metody, Python sprawdza również, czy obiekt ma __len__metodę i czy zwraca wartość większą niż zero. Może to być przydatne, jeśli utworzysz kontener sekwencji.

Zobacz także 4.1. Testowanie wartości prawdy .

Tablice i podklasy NumPy

Prawdopodobnie nieco poza zakres pierwotnego pytania, ale w przypadku, gdy masz do czynienia z tablicami lub podklasami NumPy (takimi jak Pandas Series lub DataFrames), niejawne boolwywołanie wzbudzi przerażenie 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().

W takich przypadkach można użyć funkcji logicznej i funkcji NumPy, która wykonuje element and(lub or):

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

Jeśli masz do czynienia tylko z tablicami logicznymi, możesz także użyć operatorów binarnych z NumPy, które wykonują porównania elementarne (ale także binarne):

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

Że boolwywołanie na operandach musi zostać zwrócone Truelub Falsenie jest całkowicie poprawne. To tylko pierwszy operand, który musi zwrócić wartość logiczną w swojej __bool__metodzie:

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)

Jest tak, ponieważ andfaktycznie zwraca pierwszy operand, jeśli pierwszy operand ewaluuje Falsei jeśli ewaluuje, Trueto zwraca drugi operand:

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

Podobnie, orale tylko na odwrót:

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

Jeśli jednak użyjesz ich w ifinstrukcji if, domyślnie wywoła również boolwynik. Więc te drobniejsze punkty mogą nie być dla ciebie odpowiednie.


36

Dwa komentarze:

  • Użyj andi ordo operacji logicznych w Pythonie.
  • Zamiast wcięcia użyj 4 spacji. 2. Później podziękujesz sobie, ponieważ kod będzie wyglądał tak samo jak kod wszystkich innych. Zobacz PEP 8 po więcej szczegółów.

10

Używasz andior do wykonywania operacji logicznych, takich jak w C, C ++. Jak dosłownie andjest &&i orjest|| .


Spójrz na ten zabawny przykład,

Załóżmy, że chcesz zbudować bramki logiczne w języku Python:

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

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

Teraz spróbuj do nich zadzwonić:

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

Spowoduje to:

False
True

Mam nadzieję że to pomoże!


9

Poszedłem z czysto matematycznym rozwiązaniem:

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

7
To nie jest odpowiedź na rzeczywiste pytanie.
Matthew przeczytał

5

Prawdopodobnie nie jest to najlepszy kod do tego zadania, ale działa -

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

-3

Wystarczy jeden &(nie podwójny &&) lub, jak sugeruje górna odpowiedź, możesz użyć „i”. Znalazłem to również w pandach

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

jeśli zamienimy „&” na „i”, to nie zadziała.


1
Pojedynczy i nie zwiera wyrażenia (co oznacza, że ​​oba zostaną ocenione niezależnie od wartości zwracanej pierwszego wyrażenia)
user528025

-4

może z & zamiast% jest szybszy i zapewnia lepszą czytelność

inne testy parzyste / nieparzyste

x jest parzyste? x% 2 == 0

x jest nieparzysty? nie x% 2 == 0

może jest bardziej przejrzysty z bitową i 1

x jest nieparzysty? x i 1

x jest parzyste? nie x i 1 (nieparzyste)

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

-4

Użycie „i” warunkowo. Często używam tego podczas importowania do 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

14
Na to pytanie zadano i udzielono odpowiedzi prawie 7 lat temu. Co twoja odpowiedź dodaje do tych, które już są tutaj? Ogólnie rzecz biorąc, chyba że masz coś zaskakująco nowego do powiedzenia, nie powinieneś dodawać nowej odpowiedzi do starego pytania - gdzie stare jest mierzone jako wiele lat - gdy są już dostępne dobre odpowiedzi.
Jonathan Leffler
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.