[PYTHON] Valeur de retour de quit () -Y a-t-il quelque chose retourné par la "fonction qui termine tout"?

Merci à chun et cocoatomo pour leurs réponses et articles de référence dans la communauté Discord, nous avons fait de grands progrès dans la résolution et la conviction. Merci beaucoup. Je profite de cette occasion pour vous remercier.

Le début de l'affaire

En lisant cet article, j'ai trouvé le code qui m'intéressait dans les commentaires de l'article.

x = f"{quit()}"
while True:
    print("hello")

Comme l'a dit le contributeur du commentaire de l'article, lorsque j'exécute ce code, «bonjour» n'est pas affiché et il se termine.

Je me sentais un peu mal à l'aise ici, alors j'ai cherché.

Concernant la f-string, selon le Document officiel,

Le littéral de chaîne formaté ou chaîne f est un littéral de chaîne préfixé par «f» ou «F». Ces chaînes peuvent contenir des champs de remplacement, qui sont des expressions séparées par des crochets ondulés {}. Les littéraux de chaîne formatés sont évalués comme des expressions au moment de l'exécution, tandis que les autres littéraux de chaîne sont toujours constants et ne changent pas.

Et cela. Cela signifie que si vous mettez une fonction à l'intérieur de {}, elle remplacera sa valeur de retour par un champ. Formate en une chaîne, que la valeur de retour de la fonction soit int, list ou dict. En fin de compte, f-string est une chose blanche assez puissante qui transforme même NoneType en une chaîne " None ".

** Ce que la fonction quit () qui a cassé cette puissante f-string a renvoyé **

C'était ma première question.

Approche 1 Voir type ()

Tout d'abord, j'ai pensé que je pourrais voir un indice si je savais quel type de "type" quit () renvoyait, j'ai donc exécuté le code suivant.

>>> print(type(quit()))

C:\work>

Rainy day ** l'interpréteur python lui-même est terminé **

Comme mentionné ci-dessus, si la valeur de retour est NoneType, la chaîne "" None "` sera sortie lorsque vous la mettez dans f-string, donc je m'attendais à ce que la valeur de retour de quit () ne soit pas NoneType. Au lieu de n'obtenir aucun résultat, l'interpréteur entier est abandonné ...

Approche 2 Voir la partie définition des fonctions

Même si vous ne pouvez pas obtenir le type, vous pouvez voir ce que vous faites en regardant la source de la fonction quit () réelle. J'ai pensé, et j'ai jeté un coup d'œil à quit dans le builtin.

builtin.pyi


def quit(code: object = ...) -> NoReturn: ...

** Il n'y a pas de retour en premier lieu, et le mystérieux No Return prétend que ce n'est pas une omission ou une erreur **

J'ai pris pour acquis que la fonction avait un retour, donc j'étais déjà épuisé et j'ai décidé de poser une question dans la communauté Discord.

L'approche 3 m'a appris

J'ai pu obtenir une réponse de la communauté. Je vais le citer.

sys.exit (), exit (), quit () donne l'impression de lancer une exception SystemExit Référence: https://docs.python.org/3/library/constants.html

  1. Évaluer à l'intérieur {}
  2. Lancez une exception Conclusion: il ne sera pas exécuté après la deuxième ligne Je pense que c'est comme Je pense que NoReturn est en train de taper. Référence: https://docs.python.org/3/library/typing.html Si vous ne spécifiez pas la valeur de retour de la fonction (si vous n'utilisez pas return), None sera automatiquement retourné, donc ce n'est pas No Return. def nom de la fonction () -> Aucun: pass

En d'autres termes, quit (), sys.exit (), exit (), etc. sont des ** fonctions qui donnent toujours des exceptions **.

Identité d'exception et aucun retour

Quant à l'exception SystemExit que vous m'avez indiquée, même si vous exécutez normalement quit () ou sys.exit (), vous ne pouvez pas attraper l'exception et aucun traceback n'apparaît. En effet, les exceptions SystemExit ne sont pas des ** Exceptions, mais héritent directement de BaseException, la classe principale dont elles héritent. Il semble que les exceptions qui peuvent être interceptées normalement, KeyError et TypeError, sont héritées de la classe Exception, et SystemExit ne s'y trouve pas.

À propos de BaseException

** BaseException est le chef-d'œuvre de toutes les exceptions python **, et il n'y a que quatre classes d'exceptions qui en héritent directement: SystemExit, GeneratorExit, KeyboardInterrupt et Exception.

L'interruption du clavier est «Ctrl + C». Exception est la classe de base pour toutes les autres exceptions, et les exceptions définies par l'utilisateur doivent également être basées sur cela. Lorsque vous écrivez du code avec une erreur, ce qui est capturé et produit par Traceback est celui qui hérite de cette classe Exception, et l'exception qui hérite directement de BaseException n'est pas interceptée.

Utilisez le module de traceback pour intercepter une BaseException. Attrapons l'exception SystemExit que nous prévoyons de se produire sur la première ligne du code d'ouverture.

import traceback
try:
    x = f"{quit()}"
    print(x)
except BaseException: #BaseException est spécifié au cas où, mais sauf:Mais ils le ramasseront
    print(traceback.format_exc())

Le résultat est le suivant

python


Traceback (most recent call last):
  File "c:/work/catchBaseException.py", line 3, in <module>
    x = f"{quit()}"
  File "C:\Python\Python37\lib\_sitebuiltins.py", line 26, in __call__
    raise SystemExit(code)
SystemExit: None

** J'ai pu attraper la sortie système de BaseException en toute sécurité **

À propos de aucun retour

Ce n'est pas si difficile, c'est un indice de type ou un résultat attendu.

À l'origine, il semble que la fonction retourne implicitement None lorsque return n'est pas spécifié. Par exemple, le code suivant

python


def no_return():
    pass

x = no_return()
print(type(x))


<class 'NoneType'>

Loin de return None, return lui-même n'est pas défini dans la fonction no_return (), mais le type de retour est NoneType. En d'autres termes, la fonction no_return est implicitement «return None». Cependant, c'est le cas lorsque la fonction est exécutée normalement jusqu'à la fin et qu'il n'y a pas de retour.

** quit () et sys.exit () qui crachent une exception ne retournent même pas implicitement None **

L'indication de type d'une fonction décrit la valeur attendue du type renvoyé par la fonction, mais le résultat attendu de ces fonctions que même None ne renvoie pas est que le contenu de l'indication de type est «NoReturn». Cela semble être ainsi.

Résumé

--quit (), sys.exit () déclenche une exception SystemExit --SystemExit est un système spécial qui hérite directement de la classe d'exception principale BaseException. --Une fonction qui ne spécifie pas renvoie implicitement return None, mais ce n'est même pas fait par l'exception SystemExit, et le résultat de l'exécution ne retourne même pas None.

Lien de référence

Documentation officielle https://docs.python.org/ja/3/library/constants.html https://docs.python.org/ja/3/library/exceptions.html#SystemExit https://docs.python.org/ja/3/library/typing.html#typing.NoReturn Qiita https://qiita.com/ksato9700/items/44caf7bf0329fb987499 https://qiita.com/hayata-yamamoto/items/259238dad038b5bee51c Discord officiel de Pythonjp https://www.python.jp/pages/pythonjp_discord.html

Recommended Posts

Valeur de retour de quit () -Y a-t-il quelque chose retourné par la "fonction qui termine tout"?
L'histoire selon laquelle la valeur de retour de tape.gradient () était None
À propos de la valeur de retour de pthread_mutex_init ()
À propos de la valeur de retour de l'histogramme.
Trouvez la valeur minimale de la fonction par la méthode d'optimisation du groupe de particules (PSO)
Attention à la valeur de retour de __len__
La valeur de pyTorch torch.var () n'est pas distribuée
La valeur de retour (générateur) d'une fonction qui combine finally et yield ne doit pas être passée directement à next
Rechercher par la valeur de l'instance dans la liste
[Python of Hikari-] Chapitre 06-02 Fonction (argument et valeur de retour 1)
Autour de l'endroit où la valeur d'Errbot est stockée
#Une fonction qui renvoie le code de caractère d'une chaîne de caractères
La méthode de copie de pandas.DataFrame est une copie profonde par défaut
[Linux] [C / C ++] Comment obtenir la valeur d'adresse de retour d'une fonction et le nom de fonction de l'appelant
La valeur de meta lors de la spécification d'une fonction sans valeur de retour avec Dask dataframe s'applique
La valeur de retour de len ou unichr peut changer selon qu'il s'agit de UCS-2 ou UCS-4.