L'équivalent de && (logique-et) de Python dans une instruction if

830

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

Je reçois une erreur dans le conditionnel IF .
Qu'est-ce que je fais mal?

Arsen Khachaturyan
la source
10
Il est clair que Sergio voulait savoir pourquoi son code était cassé, mais j'ai lu un peu plus dans le titre de la question. Pourquoi && ne serait-il pas disponible de toute façon? == et! = sont disponibles (mais sont différents de l'est et ne le sont pas, je sais). Pourquoi ne pas inclure cette syntaxe? Préférence personnelle?
physicsmichael
5
@ vgm64: Pourquoi inclure une syntaxe redondante qui n'améliore pas un seul aspect?
Konrad Rudolph
27
Il me semble que l'interprète devrait, plutôt que d'imprimer une "SyntaxError: syntaxe invalide" cryptique - détecter que l'utilisateur a utilisé &&et lui suggérer qu'il pourrait vouloir utiliser le mot-clé à la andplace. Il en va de même pour des choses comme ++et d'autres opérateurs communs d'autres langues.
ArtOfWarfare
3
@physicsmichael "il devrait y avoir une, et de préférence une seule façon évidente de le faire." import this
Nick T
3
@KonradRudolph Il améliore absolument les aspects de la langue. Il est plus cohérent et intuitif pour quiconque a déjà utilisé une autre langue. le fait que cette question existe et ait autant de trafic qu'elle le met clairement en évidence comme un point de blocage commun pour les gens.
jterm

Réponses:

1473

Vous voudriez andau lieu de &&.

ChristopheD
la source
2
que dois-je faire pour cela: si x == 'n' et y == 'a' ou y == 'b': <faire quelque chose> Est-ce que ça fonctionnera!? @ChristopheD
diffracteD
7
@diffracteD: Utilisez des parenthèses si vous souhaitez remplacer la priorité standard des opérateurs (que vous pouvez découvrir ici: ibiblio.org/g2swap/byteofpython/read/operator-precedence.html )
ChristopheD le
3
J'aime que David Titarenco a donné une coupe-n-coller par exemple
Alexx Roche
7
Je suis arrivé ici après avoir tapé les deux &&et ANDj'ai eu une erreur (je ne m'attendais pas à ce que python veuille le mot en minuscule and).
Xeoncross
2
Je pense que vous devriez utiliser & See: stackoverflow.com/questions/36921951/…
user1761806
229

Utilisations andet orconditions de Python .

c'est à dire

if foo == 'abc' and bar == 'bac' or zoo == '123':
  # do something
David Titarenco
la source
5
N'oubliez pas que python n'a pas non plus (enfin, et!)
inspectorG4dget
9
Votre exemple évalue-t-il "(si ceci et ceci) ou cela" OU "si ceci et (ceci ou cela)"?
Jeff
12
@Jeff Votre première façon. and a une priorité plus élevée que or.
Buge
1
@Buge il ressemble à "ou" est plus haut dans le tableau que vous avez lié
Matt
5
@Matt la table passe de la priorité la plus basse à la plus élevée. Il est plus facile de se rappeler la priorité si vous avez étudié l'algèbre booléenne; "ou" est l'addition et "et" est la multiplication.
Michael Stroud
48

Je reçois une erreur dans le conditionnel IF. Qu'est-ce que je fais mal?

La raison pour laquelle vous obtenez un SyntaxErrorest qu'il n'y a pas d' &&opérateur en Python. De même ||et ne! sont pas des opérateurs Python valides .

Certains des opérateurs que vous connaissez peut-être dans d'autres langues ont un nom différent en Python. Les opérateurs logiques &&et ||sont en fait appelés andet or. De même, l'opérateur de négation logique !est appelé not.

Vous pouvez donc simplement écrire:

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

ou même:

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

Quelques informations supplémentaires (qui pourraient être utiles):

J'ai résumé l'opérateur "équivalents" dans ce tableau:

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

Voir aussi la documentation Python: 6.11. Opérations booléennes .

Outre les opérateurs logiques, Python possède également des opérateurs binaires / binaires:

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

Il n'y a pas de négation au niveau du bit en Python (juste l'opérateur inverse au niveau du bit ~- mais ce n'est pas équivalent à not).

Voir aussi 6.6. Opérations arithmétiques unaires et au niveau du bit / binaire et 6.7. Opérations arithmétiques binaires .

Les opérateurs logiques (comme dans beaucoup d'autres langues) ont l'avantage d'être court-circuités. Cela signifie que si le premier opérande définit déjà le résultat, le deuxième opérateur n'est pas évalué du tout.

Pour le montrer, j'utilise une fonction qui prend simplement une valeur, l'imprime et la renvoie à nouveau. C'est pratique pour voir ce qui est réellement évalué en raison des instructions d'impression:

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

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

Comme vous pouvez le voir, une seule instruction print est exécutée, donc Python n'a même pas regardé l'opérande approprié.

Ce n'est pas le cas pour les opérateurs binaires. Ceux-ci évaluent toujours les deux opérandes:

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

Mais si le premier opérande ne suffit pas, alors, bien sûr, le deuxième opérateur est évalué:

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

Pour résumer ceci, voici un autre tableau:

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

Les Trueet Falsereprésentent ce qui bool(left-hand-side)retourne, ils n'ont pas à être Trueou False, ils ont juste besoin de revenir Trueou Falsequand boolest appelé sur eux (1).

Ainsi, dans le pseudo-code (!) and, Les orfonctions et fonctionnent comme suit:

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)

Notez qu'il s'agit de pseudo-code et non de code Python. En Python, vous ne pouvez pas créer de fonctions appelées andou orparce que ce sont des mots clés. De plus, vous ne devez jamais utiliser "évaluer" ou if bool(...).

Personnalisation du comportement de vos propres classes

Cet boolappel implicite peut être utilisé pour personnaliser le comportement de vos classes avec and, oret not.

Pour montrer comment cela peut être personnalisé, j'utilise cette classe qui, encore printune fois, permet de suivre ce qui se passe:

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)

Voyons donc ce qui se passe avec cette classe en combinaison avec ces opérateurs:

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

Si vous n'avez pas de __bool__méthode, Python vérifie également si l'objet a une __len__méthode et s'il renvoie une valeur supérieure à zéro. Cela peut être utile de savoir si vous créez un conteneur de séquence.

Voir aussi 4.1. Test de valeur de vérité .

Tableaux et sous-classes NumPy

Probablement un peu au-delà de la portée de la question d'origine, mais dans le cas où vous avez affaire à des tableaux ou sous-classes NumPy (comme Pandas Series ou DataFrames), l' boolappel implicite augmentera le redouté 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().

Dans ces cas, vous pouvez utiliser la logique et la fonction de NumPy qui effectue un élément and(ou 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])

Si vous traitez uniquement avec des tableaux booléens, vous pouvez également utiliser les opérateurs binaires avec NumPy, ceux-ci effectuent des comparaisons par élément (mais aussi binaire):

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

Que l' boolappel sur les opérandes doit retourner Trueou Falsen'est pas complètement correct. C'est juste le premier opérande qui doit retourner un booléen dans sa __bool__méthode:

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)

C'est parce andque retourne en fait le premier opérande si le premier opérande évalue à Falseet s'il évalue à Truealors il retourne le deuxième opérande:

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

De même pour ormais juste l'inverse:

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

Toutefois, si vous les utilisez dans une ifinstruction, le résultat ifinvoquera également implicitement boolle résultat. Ces points plus fins peuvent donc ne pas être pertinents pour vous.

MSeifert
la source
36

Deux commentaires:

  • Utilisez andet orpour les opérations logiques en Python.
  • Utilisez 4 espaces pour mettre en retrait au lieu de 2. Vous vous remercierez plus tard, car votre code sera à peu près le même que le code de tout le monde. Voir PEP 8 pour plus de détails.
dérangeant
la source
10

Vous utilisez andetor pour effectuer des opérations logiques comme en C, C ++. Comme andest &&et orest|| littéralement .


Jetez un oeil à cet exemple amusant,

Supposons que vous souhaitiez créer des portes logiques en Python:

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

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

Essayez maintenant de les appeler:

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

Cela produira:

False
True

J'espère que cela t'aides!

geekidharsh
la source
9

Je suis allé avec une solution purement mathématique:

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:]
Gros rouge
la source
7
Ce n'est pas une réponse à la vraie question.
Matthieu lu
5

Ce n'est probablement pas le meilleur code pour cette tâche, mais cela fonctionne -

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
la source
-3

Un simple &(pas double &&) est suffisant ou comme la réponse du haut suggère que vous pouvez utiliser 'et'. J'ai aussi trouvé ça chez les pandas

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

si nous remplaçons le "&" par "et", cela ne fonctionnera pas.

William You
la source
1
Single & ne court-circuite pas l'expression (ce qui signifie que les deux seront évalués quelle que soit la valeur de retour de la première expression)
user528025
-4

peut-être qu'avec & au lieu de cela% est plus rapide et maintient la lisibilité

autres tests pairs / impairs

x est pair? x% 2 == 0

x est impair? pas x% 2 == 0

est peut-être plus clair avec bit à bit et 1

x est impair? x & 1

x est pair? pas x & 1 (pas impair)

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
Chute de fil
la source
-4

Utilisation de "et" au conditionnel. J'utilise souvent cela lors de l'importation dans 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
la source
14
Cette question a été posée et répondue il y a près de 7 ans. Qu'est-ce que votre réponse ajoute à ces réponses qui sont déjà là? En général, à moins que vous n'ayez quelque chose de nouveau à dire, vous ne devez pas ajouter une nouvelle réponse à une ancienne question - où l'ancienne est mesurée sur plusieurs années - alors qu'il existe déjà de bonnes réponses.
Jonathan Leffler