Souligner en Python

J'ai récemment eu la chance d'écouter un exposé sur les bonnes et les mauvaises pratiques de programmation en C. Dans ce document, en particulier, le sujet du décodage de code de programme drôle ( émoticônes en C) a été abordé. Puis il y a eu un débat sur l'opportunité d'utiliser un tel code déroutant pour tester les compétences d'un candidat à un poste de programmeur lors des entretiens. Le différend n'a pas abouti à un consensus.

Considérez une question possible sur les émoticônes lors d'une interview pour un poste qui implique la connaissance du langage de programmation Python.

Défi


Il existe deux expressions:

  1. _+_ 
  2.  _|_ 

Laquelle de ces deux expressions entraînera le plus probablement des erreurs et pourquoi?

Notes d'expression
Il convient de noter que ces expressions sont mal lues, de telles expressions ne sont pas recommandées à utiliser dans le code de travail, mais ne peuvent être utilisées que comme puzzle.
Vous devez également vous rappeler que les émoticônes de la tâche ne sont pas écrites en python (ne sont pas conformes à la norme de style PEP 8 ).

Solution


En Python, le trait de soulignement n'est pas un mot - clé ; par conséquent, en général, il peut être utilisé pour affecter certaines valeurs à des variables.

La tâche est réduite à la prise en compte des cas d'erreurs lors de l'addition et avec «bit ou» (pour plus de concision, simplement «ou») une variable. C'est-à-dire pour rechercher les types intégrés Python (classes) pour lesquels une opération est implémentée et pour rechercher les types intégrés dans lesquels une autre opération est implémentée.

Dans la console Python, il est facile de vérifier qu'il existe des valeurs de soulignement telles que:

  1. Il n'y a pas d'erreur dans l'évaluation de chaque expression
     >>> _ = 10 >>> _+_ 20 >>> _ = 10 >>> _|_ 10 
  2. Il n'y a pas d'erreur dans l'évaluation de la première expression
     >>> _ = '10' >>> _+_ '1010' >>> _ = '10' >>> _|_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'str' and 'str' 
  3. Il n'y a pas d'erreur dans le calcul de la deuxième expression
     >>> _ = {1, 0} >>> _+_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'set' and 'set' >>> _|_ {0, 1} 
  4. Il y a une erreur dans le calcul de chaque expression
     >>> _ = {1: 0} >>> _+_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'dict' and 'dict' >>> _|_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'dict' and 'dict' 

La magie de Python est que l'implémentation des ajouts, et «ou», et d'autres opérateurs est dans les soi-disant «méthodes magiques» décrites pour les classes requises.
De plus, c'est la méthode

 __add__ 

Pour "ou", c'est une méthode

 __or__ 

Le nom de chaque méthode magique contient des traits de soulignement, deux au début et à la fin du mot correspondant.

Recherche d'informations sur les classes intégrées Python.
Vous pouvez essayer de trouver les informations requises dans la documentation des types intégrés sur le site Web officiel de Python: https://docs.python.org/3.7/library/stdtypes.html .
Vous pouvez exécuter dans un terminal Python

 >>> import builtins >>> help(builtins) 

Je préfère utiliser la documentation de la version exacte de Python que j'utilise actuellement, en faisant référence à l'interface Web du module pydoc.

Pour ce faire, à l'invite de commande, entrez, par exemple:

 python3 -m pydoc -p 3344 

et ouvrez le module de documentation du navigateur http: // localhost: 3344 / builtins.html .

Classes intégrées pour lesquelles nos méthodes sont implémentées:
__add____ou__
boolbool
bytearrayfrozenset
octetsint
complexeensemble
flotter
int
liste
str
tuple

Neuf classes intégrées implémentent l'opération d'addition et quatre implémentent le «ou».
En outre, vous pouvez essayer de spéculer sur la fréquence d'utilisation des classes de base dans des projets réels, sur les classes non basiques et sur la mise en œuvre des méthodes ci-dessus. Cela est susceptible d'être positivement apprécié lors de l'entretien.

Réponse 1.
La deuxième expression entraîne souvent une erreur.



Questions supplémentaires possibles sur la mise en évidence de l'entretien


Quel est le rôle du trait de soulignement dans la dénomination des objets?


Réponse 2.
Le trait de soulignement peut être utilisé pour séparer des mots dans différents styles de dénomination d'entité en Python :

  1. Lorsque vous nommez en minuscules

     lower_case_with_underscores 
  2. Lorsque vous nommez en majuscules

     UPPER_CASE_WITH_UNDERSCORES 

Certains noms limités aux traits de soulignement sont réservés :

  1. Avec un trait de soulignement au début d'un nom, il n'est pas importé lors de l'importation générale

     from module import * 
  2. Étant donné que deux traits de soulignement des deux côtés du nom sont considérés comme systémiques, il n'est pas recommandé d'utiliser ces noms à d'autres fins.
  3. Avec deux soulignements au début d'un nom, il est considéré comme privé (non public) pour la classe


Quel est le rôle d'un seul trait de soulignement?


Réponse 3.
Dans l'interpréteur, si le trait de soulignement n'a pas été explicitement utilisé comme variable, il stocke le résultat de la dernière action sans erreur affichée à l'écran.

 $ python3 Python 3.6.8 (default, Feb 14 2019, 22:09:48) [GCC 7.4.0] on cygwin Type "help", "copyright", "credits" or "license" for more information. >>> _ Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name '_' is not defined >>> 2 * 5 10 >>> _ 10 >>> _ = 1 >>> _ 1 >>> 2 * 5 10 >>> _ 1 

En effet, sys.stdout s'échappe avec displayhook . Prenons un exemple de la documentation officielle :

 def displayhook(value): if value is None: return # Set '_' to None to avoid recursion builtins._ = None text = repr(value) try: sys.stdout.write(text) except UnicodeEncodeError: bytes = text.encode(sys.stdout.encoding, 'backslashreplace') if hasattr(sys.stdout, 'buffer'): sys.stdout.buffer.write(bytes) else: text = bytes.decode(sys.stdout.encoding, 'strict') sys.stdout.write(text) sys.stdout.write("\n") builtins._ = value 

De plus, un seul soulignement est couramment utilisé pour faciliter l' internalisation .

Source: https://habr.com/ru/post/fr459672/


All Articles