Intéressant et utilité de python. 2e partie

Dans l' article précédent, nous avons examiné plusieurs points intéressants du langage python, bien sûr, ils ne sont pas limités à un seul article, nous allons donc continuer.

Un commentaire a examiné le code suivant:

SEX = 'Female', 'Male' sex = SEX[True] # -> Male sex = SEX[False] # -> Female 

Cela fonctionne parce que le type de données logique est équivalent à 0 et 1, de plus, au début, il n'y avait pas de type spécial et les valeurs 0 et 1 étaient utilisées. Et quand il a été entré, nous avons décidé d'hériter de l'ensemble.

 print(int.__subclasses__()) # -> [<class 'bool'>] 

Mais revenons à l'obtention des valeurs de la liste, disons que nous avons les données suivantes:

 books = [["Sherlock Holmes", "Arthur Conan Doyle", 1986, True, 12.51], ["The Lost World", "Arthur Conan Doyle", 2015, False, 5.95], ["The Art of Computer Programming", "Donald E. Knuth ", 2017, True, 190.54] ] 

Bien sûr, faire référence aux valeurs par des indices codés en dur n'est pas notre chemin. Vous pouvez créer une constante, par exemple AUTHOR et la spécifier, mais vous pouvez aller plus loin:

 TITLE_AUTHOR = slice(0, 2) PRICE_IN_STOCK = slice(3, 5) print(books[0][TITLE_AUTHOR]) print([book for book in books if book[PRICE_IN_STOCK] > [True, 10.0]]) 

Nous pouvons créer un objet tranche et lui indiquer à quels index se trouvent les champs d'intérêt. Nous pouvons même être assez courageux pour écrire quelque chose de similaire à la dernière ligne de ce bloc, qui affiche des livres disponibles dans l'entrepôt et plus chers que 10 autres. Ce code fonctionnera, car la comparaison des listes et des tuples a lieu lexicographiquement: d'abord les premiers éléments sont comparés, puis le second et ainsi de suite, c'est-à-dire que tout objet dont le in_stock «field» est faux sera plus petit que la liste [True, 10.0], puisque Vrai> Faux.

Remarque: bien sûr, ce code ne doit pas être utilisé dans les projets, mais il est préférable de se limiter à simplement obtenir des valeurs pour la tranche, il est préférable de faire des sélections dans la base de données, soit dans Pandas, soit comme méthode de la classe Book. Vous pouvez utiliser namedtuple et écrire un petit module où placer des méthodes avec des sélections similaires.

Nous avons déjà considéré les arguments qui peuvent être passés à la fonction uniquement par clé. Récemment, en étudiant la documentation de la fonction bool , j'ai trouvé un indice:
Modifié dans la version 3.7: x est désormais un paramètre positionnel uniquement.
Maintenant, PEP 570 est en cours de développement, ce qui ouvrira la possibilité de définir de tels paramètres, cela peut être utile lorsque le nom du paramètre n'a pas d'importance, comme bool (), pow (), etc.

Le projet de syntaxe ressemble à ceci:

 def name(positional_only_parameters, /, positional_or_keyword_parameters, *, keyword_only_parameters): 

Revenir à la fonction bool, qui fonctionne exactement comme la vérification des conditions et des boucles lorsque vous exécutez du code

 if obj: #  while obj: 

python effectue une procédure assez intéressante pour sortir une valeur booléenne:

  1. Si l'objet implémente la méthode __bool __ (), le résultat de l'appel de cette méthode est renvoyé
  2. Sinon, il est vérifié si la méthode __len __ () est implémentée, si c'est le cas, alors il est vérifié qu'elle retourne, si 0, alors le résultat sera faux.
  3. Si aucune méthode n'est implémentée, True est renvoyée.

 class A: pass a = A() print(bool(a)) # -> True 

Les entiers implémentent la méthode __bool__, les collections standard ne l'implémentent pas, mais implémentent la méthode __len__:

 print(dir(int)) # -> ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', ... print(dir(list)) # -> ['__add__', '__class__', '__contains__', ... 

Dans un autre commentaire , le comportement "non standard" des attributs de classe a été donné:

 class Example: arr=[] def __init__(self): pass a = Example() b = Example() a.arr.append(1) print(a.arr) # -> [1] print(b.arr) # -> [1] print(Example.arr) # -> [1] 

Il est très important de faire la distinction entre les attributs d'une classe et d'un objet ; les attributs d'un objet sont créés, SOUDAINEMENT, à partir de l'objet.
Il est important de comprendre que tous les champs et méthodes déclarés dans le corps de classe appartiennent à la classe. Pour créer un attribut pour un objet, vous devez l'attribuer à l'objet, dans la méthode de classe via self ou dans le texte du programme, via la variable objet.

Si vous êtes confus, analysons le code précédent, deux instances de la classe y sont créées, après quoi 1 est ajouté au champ arr via l'un des objets. Mais il n'y a pas un tel attribut dans l'objet, le constructeur est vide, donc python recherche cet attribut dans la classe et le trouve, mais il est partagé par toutes les instances de la classe. Vous pouvez vérifier qu'il s'agit de l'attribut de la classe sur la dernière ligne, car l'accès à la classe par le nom de cet attribut n'a généré aucune erreur.

Lors de l'apprentissage d'une nouvelle langue, il est important de comprendre que chaque langue a sa propre philosophie et que toutes les langues ne doivent pas avoir le mot-clé statique. Parfois, un mécanisme similaire est fourni par d'autres mécanismes.

Plus clairement, l'idée que python n'est pas java illustre que l'ajout de champs dans les objets et les classes se fait par l'affectation habituelle:

 def make_title(self): if self.title == 'Mister': return 'Mr. ' + self.surname class Person: pass john = Person() john.title = 'Mister' john.name = 'John' john.surname = 'Peterson' john.age = 33 Person.make_title = make_title print(john.make_title()) 

Recommandation générale: ne stockez pas les types mutables comme instances de la classe, c'est difficile, cependant, si vous savez ce que vous faites, utilisez cette fonctionnalité au maximum, l'essentiel est de réfléchir soigneusement à tout au début et de documenter après.

Par exemple, il est très simple de créer une classe qui stocke des liens vers toutes ses instances:

 class RememberAll(): instances = [] def __init__(self): self.instances.append(self) a = RememberAll() b = RememberAll() print(RememberAll.instances) #-> [<__main__.RememberAll object at 0x7faa4a5ab7b8>, <__main__.RememberAll object at 0x7faa4a523c88>] 

Vous pouvez implémenter la classe d'un objet physique et, lors du changement de ses caractéristiques, appeler des méthodes pour recalculer les caractéristiques d'autres éléments du système. Ou souvenez-vous de tous les curseurs du formulaire et lorsque vous en déplacez un, déplacez automatiquement le reste. Je ne prétends pas dire qu'une telle implémentation est toujours simple, mais parfois elle peut être utile.

Eh bien, puisque nous avons abordé la physique, je veux mentionner l'opérateur @. Oui, il y en a un . Il a été introduit pour la multiplication matricielle, qui est le plus drôle, mais il semble qu'il n'ait été implémenté pour aucun des types de données standard, c'est-à-dire qu'il n'a été initialement introduit que pour les bibliothèques tierces. Mais rien ne vous empêche d'ajouter sa prise en charge pour vos types de données en implémentant les méthodes __matmul__, __rmatmul__, __imatmul__

 class Person: def __init__(self, name): self.name = name def __matmul__(self, msg): return "@" + self.name + " " + msg john = Person("John") print(john @ "hello") # -> @John hello 

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


All Articles