Pour expliquer ma requête, j'ai un simple extrait de code ci-dessous suivi de ma question.
for char in s:
donne une sortie
"" in "aeiouAEIOU"
Mon doute:
Pourquoi une chaîne vide "" renvoie True pour l'expression
0 True
Mais il saute quand il est présent avec une boucle for?
def count_vowels(s):
num_vowels = 0
for char in s:
if char in 'aeiouAEIOU':
num_vowels = num_vowels + 1
return num_vowels
print(count_vowels(""))
print("" in "aeiouAEIOU")
Ma compréhension est que les chaînes vides sont un sous-ensemble de toutes les chaînes, alors pourquoi il est ignoré lorsque la même expression est dans la boucle for? N'hésitez pas à me corriger s'il y a quelque chose qui me manque ici.
3 Réponses :
Dans la deuxième commande d'impression que vous demandez, "" apparaît-il dans "aeiouAEIOU" et c'est True . Cependant, la longueur de "" est égale à 0. Ainsi, la boucle for ne s'exécute pas une seule fois car il n'y a aucun élément à parcourir.
Je ne demande pas de solution. Je demande pourquoi la fonction count_vowels("") ignore la boucle for? lorsque l'expression autonome "" in "aeiouAEIOU" est Vrai en soi. Essayez le débogage dans Pyton vizualiser et voyez par vous-même. Je suis surpris que cela n'ait pas été demandé auparavant sur Stack Overflow
Merci pour cette clarification, car la longueur de s est de 0, il n'y a donc rien à parcourir.
Au vu des réponses et commentaires unanimes, je devrai considérer que le comportement est intentionnel. Je remettais toujours en question le design et non le code.
Votre compréhension est correcte: "les chaînes vides sont un sous-ensemble de toutes les chaînes"
Mais voyons maintenant ce qui se passe lorsque nous utilisons for pour un type de séquence tel que string. Disons que nous avons:
index = 0
while True:
try:
i = lst.__getitem__(index)
except IndexError:
break
print(i ** 2)
index += 1
Il s'agit en fait de:
lst = [1, 2, 3, 4, 5]
for i in lst:
print(i ** 2)
Dans votre exemple, quand il essaie d'obtenir même le premier élément, il lèvera une exception et sortira de la boucle. Donc, il n'entre même pas dans la boucle For .
Vous voulez donc dire qu'il existe un mécanisme try-catch que python a dans son implémentation de boucle for qui fait que le code ignore la boucle? Si tel est le cas, votre réponse sera considérée comme acceptée. Mais cela aiderait si vous fournissiez un lien de documentation pour preuve.
Oui, il existe un mécanisme d'essai, mais ce n'est pas celui que présente cet article. Recherchez StopIteration .
@mishsx oui. la meilleure preuve est d'essayer d'implémenter vous-même un type de séquence. Comme vous le savez, vous devez implémenter la méthode __getitem__ . Dans cette fonction, vous devez en quelque sorte indiquer qu'il ne s'agit pas d'un index valide et pour ce faire, vous déclenchez une exception "IndexError". Mais en conséquence, vous pouvez voir qu'il sera réduit au silence par python. Comment ? car il existe un mécanisme d'essai sauf que "For" gère cela pour vous. (comme je l'ai mentionné dans la réponse)
@SorousHBakhtiary Merci monsieur. Votre réponse est très appréciée. Il capture l'essence de ce que je recherchais.
@mishsx heureux de vous aider. Au cas où vous voudriez implémenter un Iterator, vous devez faire presque la même chose ( For faire autre chose avec les Iterators) dans la méthode __next__ . Au lieu de cela, vous générez un StopIteration. À la fin, il sera à nouveau réduit au silence par For .
L'expression "" in s renvoie True pour toutes les chaînes s , car la chaîne vide est trivialement contenue dans toutes les chaînes: l'expression A in B revient à poser la question - y a-t-il une paire d'indices i et j tels que B[i:j] == A â € ™. Si A est la chaîne vide, nous pouvons toujours simplement mettre i et j à zéro, donc la réponse est oui.
Cependant, l'itération sur les points de code de la chaîne vide ne donne pas "" , cela ne donne rien du tout. Observer:
iterating over 'abc' item: 'a' item: 'b' item: 'c' iteration done iterating over 'ðªðº' item: 'ðª' item: 'ðº' iteration done iterating over '' iteration done
Le code ci-dessus s'imprimera:
def iterate(what):
print("iterating over {}".format(repr(what)))
for item in what:
print("item: {}".format(repr(item)))
print("iteration done")
print()
iterate("abc")
iterate("ðªðº")
iterate("")
Dans votre exemple, le corps de la boucle ne fonctionnera jamais, donc il n'incrémentera jamais le compteur de voyelles.
C'est un excellent exemple. Bien que ma question se concentre davantage sur la façon dont l'expression " in "aeiouAEIOU" donne un vrai mais pas avec une boucle for. Cependant, d'après votre exemple, il semble que cela fonctionne différemment avec une boucle for.
Il ne contient aucun caractère donc la boucle dans
count_vowelsest immédiatement quittée, hein?@bipll C'est bien mais ma question est pourquoi? Avez-vous vu l'expression d'impression? Il renvoie True. Donc, je demande en fait pourquoi la boucle for ignore une expression True?
@mishsx la boucle for ne saute pas une "expression vraie". Jamais une seule fois n'est
char == ''. L'itération sur les chaînes est bien définie, à quoi vous attendiez- vous?@ juanpa.arrivillaga D'accord, donc une question de suivi est que
charest une variable d'itération de la boucle for et donc je m'attendais à ce qu'il prenne la valeur de""et n'entre dans la boucle for qu'une seule fois et que la fonction renvoie 1jetez un œil à cette documentation: évaluez la chaîne vide de python
@mishsx iteation over strings itère sur les caractères d'une chaîne. La chaîne vide, par définition, n'a pas de caractères . Son objectif est de servir de version vide d'une chaîne. Je suppose qu'il pourrait y avoir une convétion, comme, le dernier caractère d'une chaîne sera toujours une chaîne vide, mais il n'y a pas une telle convention, et je vois peu de valeur pour cela. Dans tous les cas, ce n'est tout simplement pas ainsi que cela fonctionne.
Et notez, je suppose que les objets
stront l'étrange caractéristique que l'itération sur eux produit des objets du même type , puisque python n'a pas de type "char", il s'agit simplement de chaînes de longueur 1.@ juanpa.arrivillaga C'est très bien. Je sais que c'est aussi ainsi que cela se comporte chez l'interprète. J'étais juste curieux de savoir comment la même expression se comporte différemment avec une boucle for.
@mishsx lorsque vous évaluez cette expression comme argument à imprimer, vous obtenez sa valeur booléenne qui est
True. Lorsque vous l'évaluez dans une boucle de corps, vous ne l'évaluez pas une seule fois car le corps n'est jamais entré car la chaîne itérée est vide.