Outils pour utilisateurs

Outils du site


issue168:python

As many of you know or have at least heard, Python 3.10 is well on its way. According to python.org (https://www.python.org/dev/peps/pep-0619/), the final date for release is slated for October 4, 2021 with feature freeze scheduled for May 3, 2021. Here is the release schedule as of April 2021: • 3.10.0 alpha 7: Tuesday, 2021-04-06 Expected: • 3.10.0 beta 1: Monday, 2021-05-03 (No new features beyond this point.) • 3.10.0 beta 2: Tuesday, 2021-05-25 • 3.10.0 beta 3: Thursday, 2021-06-17 • 3.10.0 beta 4: Saturday, 2021-07-10 • 3.10.0 candidate 1: Monday, 2021-08-02 • 3.10.0 candidate 2: Monday, 2021-09-06 (if necessary) • 3.10.0 final: Monday, 2021-10-04

Comme beaucoup d'entre vous le savent ou en ont au moins entendu parler, Python 3.10 est en bonne voie. Selon python.org (https://www.python.org/dev/peps/pep-0619/), la date finale de sortie est prévue pour le 4 octobre 2021 et le gel des fonctionnalités pour le 3 mai 2021.

Voici le calendrier de publication à partir d'avril 2021 : ••3.10.0 alpha 7 : mardi 06-04-2021. Attendu : ••3.10.0 beta 1 : lundi 03-05-2021 (pas de nouvelles fonctionnalités au-delà de ce point). ••3.10.0 beta 2 : Mardi 25-05-2021. ••3.10.0 beta 3 : jeudi 17-06-2021. ••3.10.0 beta 4 : samedi 10-07-2021. ••3.10.0 candidate 1 : lundi 02-08-2021. ••3.10.0 candidate 2 : lundi 06-09-2021 (si nécessaire). ••3.10.0 final : Lundi 04-10-2021.

Just because we have over 5 months before the actual release is due, that doesn’t mean that you can’t start getting prepared and excited about the upcoming new version. Some of the changes that are supposed to be coming are: • PEP 604 – Allow writing union types as X | Y • PEP 612 – Parameter Specification Variables • PEP 626 – Precise line numbers for debugging and other tools • PEP 597 – Add optional EncodingWarning • PEP 618 – Add Optional Length-Checking To zip • PEP 644 – Require OpenSSL 1.1.1 or newer • PEP 632 – Deprecate distutils module • PEP 613 – Explicit Type Aliases And I’ve saved the best for last - • PEP 634, PEP 635 Structural Pattern Matching

Ce n'est pas parce qu'il reste plus de 5 mois avant la sortie de la nouvelle version que vous ne pouvez pas commencer à vous préparer et à vous enthousiasmer pour la version à venir. Certains des changements qui sont censés arriver sont : ••PEP 604 - Permettre l'écriture des types d'union comme X | Y. ••PEP 612 - Variables de spécification de paramètres. ••PEP 626 - Numéros de ligne précis pour le débogage et autres outils. ••PEP 597 - Ajout d'un EncodingWarning optionnel. ••PEP 618 - Ajout d'un contrôle de longueur optionnel pour zip. ••PEP 644 - Nécessite OpenSSL 1.1.1 ou plus récent. ••PEP 632 - Dépréciation du module distutils. ••PEP 613 - Alias de types explicites.

Et j'ai gardé le meilleur pour la fin - ••PEP 634, PEP 635 Correspondance de motifs structurels.

Each of the new features that are listed above have the PEP (Python Enhancement Proposals) numbers with them so you can easily do a web search for the ones you are interested in exploring. For the rest of the article, I will be discussing the new Pattern Matching feature. If you want to try out any of these things, hopefully you have pyenv installed. That way you can simply do a pyenv install 3.10-dev to play with version 3.10. There are other ways to try out 3.10, but honestly pyenv is the way to go! If you would rather check out another way, try looking at https://towardsdatascience.com/all-the-important-features-and-changes-in-python-3-10-e3d1fe542fbf and search for “Installing Alpha/Beta Version”. They provide a way to load version 3.10 alongside your existing Python version(s).

Chacune des nouvelles fonctionnalités énumérées ci-dessus est associée à un numéro PEP (Python Enhancement Proposals - Propositions d'amélioration de Python). Vous pouvez donc facilement effectuer une recherche sur le Web pour trouver celles qui vous intéressent. Dans le reste de l'article, je parlerai de la nouvelle fonction de Pattern Matching (Correspondance des motifs). Si vous voulez essayer l'une de ces fonctions, j'espère que vous avez installé pyenv. Ainsi, vous pouvez simplement faire un pyenv install 3.10-dev pour jouer avec la version 3.10. Il existe d'autres moyens d'essayer la version 3.10, mais honnêtement, pyenv est le meilleur moyen ! Si vous préférez essayer une autre méthode, consultez le site https://towardsdatascience.com/all-the-important-features-and-changes-in-python-3-10-e3d1fe542fbf et cherchez « Installing Alpha/Beta Version » (Installer une version Alpha/Bêta). Ils fournissent un moyen de charger la version 3.10 à côté de votre/vos version(s) Python existante(s).

Pattern Matching You might be wondering why I’m making such a point to talk about this single item. Well, a small history lesson is in order here. For many years, programmers have been asking for Python to support Select Case (VB) or Switch Case (C#) type statements. They have been saying that it makes code much easier to read. An example of such a statement in Visual Basic would be something like this (below). Each time the subject has come up, those who make decisions about Python have said that there is no need for that. The standard if | elif | else structure works just fine (below).

Correspondance de motifs

Vous vous demandez peut-être pourquoi je tiens tant à parler de ce seul élément. Eh bien, une petite leçon d'histoire s'impose.

Depuis de nombreuses années, les programmeurs demandent que Python supporte les instructions de type Select Case (VB) ou Switch Case (C#). Ils disent que cela rend le code beaucoup plus facile à lire. Un exemple d'une telle déclaration en Visual Basic serait quelque chose comme ceci (ci-dessous).

Chaque fois que le sujet a été abordé, ceux qui prennent les décisions concernant Python ont dit que ce n'était pas nécessaire. La structure standard if | elif | else fonctionne très bien (ci-dessous).

While the Visual Basic structure might look a bit more efficient, both are (in my humble opinion) equally easy to read. That having been said, I came from a Visual Basic background and I have to admit that when I was first learning Python, I too wondered why such a simple solution like the Select Case type testing wasn’t supported. However, I got over it and learned the Python way. Python 3.10 introduces something called Structural Pattern Matching. At first glance, it is the same thing as the Select Case for VB and Switch Case for C#. Here’s the same code as above, but done with the Pattern Matching. (Top right. By the way, this won’t work without being in Python 3.10.)

Bien que la structure de Visual Basic puisse sembler un peu plus efficace, les deux sont (à mon humble avis) tout aussi faciles à lire. Ceci étant dit, je viens d'un environnement Visual Basic et je dois admettre que lorsque j'ai commencé à apprendre Python, je me suis également demandé pourquoi une solution aussi simple que le test de type Select Case n'était pas supportée. Cependant, j'ai surmonté cette difficulté et j'ai appris la façon de faire de Python.

Python 3.10 introduit quelque chose appelé Structural Pattern Matching (Correspondance de motifs structurelle). À première vue, c'est la même chose que le Select Case pour VB et le Switch Case pour C#. Voici le même code que ci-dessus, mais réalisé avec le Pattern Matching. (En haut à droite. Au fait, ceci ne fonctionnera pas sans être en Python 3.10).

When it runs, it returns: 0 Not between 1 and 10, inclusive 1 is between 1 and 5, inclusive 2 is between 1 and 5, inclusive 3 is between 1 and 5, inclusive 4 is between 1 and 5, inclusive 5 is between 1 and 5, inclusive 6 is between 6 and 8, inclusive 7 is between 6 and 8, inclusive 8 is between 6 and 8, inclusive 9 is equal to 9 or 10 10 is equal to 9 or 10 11 Not between 1 and 10, inclusive Honestly, in this example, it doesn’t look that much better than the Python if | elif version. That’s because while you can do simple things, there is no pattern to match in that case, really.

Lorsqu'il s'exécute, il renvoie :

0 pas entre 1 et 10, inclus 1 est entre 1 et 5, inclus 2 est entre 1 et 5, inclus 3 est entre 1 et 5, inclus 4 est entre 1 et 5, inclus 5 est entre 1 et 5, inclus 6 est entre 6 et 8, inclus 7 est entre 6 et 8, inclus 8 est entre 6 et 8, inclus 9 est égal à 9 ou 10 10 est égal à 9 ou 10 11 pas entre 1 et 10, inclus

Honnêtement, dans cet exemple, cela ne semble pas tellement mieux que la version if | elif de Python. En effet, même si vous pouvez faire des choses simples, il n'y a pas vraiment un motif à mettre en correspondance dans ce cas.

On the other hand, let’s look at an example of how to make this new functionality really shine. We’ll throw together a really limited and simple text adventure game. Surely you remember those, unless you are younger than 30 years old or so. The typical text adventure drops the player in the middle of a forest (usually after a night of enjoying copious amounts of adult beverages), or into a dark room inside of a castle. Since Ronnie is Scotish and both sides of my family tree shares that same root, I’ll pick the first option for our adventure. We’ll make our player a male human (since we all know that female humans are smarter than to enjoy copious amounts of adult beverages, right?).

D'autre part, voyons un exemple de la façon dont cette nouvelle fonctionnalité peut être mise en valeur. Nous allons créer un jeu d'aventure textuel très simple et limité. Vous vous en souvenez certainement, sauf si vous avez moins de 30 ans.

Le jeu d'aventure textuel typique dépose le joueur au milieu d'une forêt (généralement après une nuit passée à boire de grandes quantités de boissons pour adultes), ou dans une pièce sombre à l'intérieur d'un château. Comme Ronnie est Écossais et que les deux côtés de mon arbre généalogique ont la même racine, je vais choisir la première option pour notre aventure. Notre joueur sera un humain de sexe masculin (puisque nous savons tous que les femmes sont plus intelligentes que les hommes et qu'elles ne boivent pas de grandes quantités de boissons pour adultes, n'est-ce pas ?)

Now, our player is in a forest with a bit of a headache. There are only four directions that he can move; North, West, South and East. We will assume that the paths available to him won’t normally run him into a tree. I mean, he already has a hangover – let’s not make it any worse. Scattered throughout his journey, he will stumble over things like a sword, an axe, some gold, some silver, some diamonds, flint and steel to start a fire, and so on. I won’t be nice enough to let him find some aspirin, just because he should suffer some for his evening’s indulgences. He also will possibly run into a monster or two. Now that we’ve defined his world somewhat, let’s start looking at writing some code. We’ll need to create a couple of lists to handle the objects in the game that the player can deal with and to “hold” the items he’s picked up (above).

Maintenant, notre joueur se trouve dans une forêt et a un peu mal à la tête. Il ne peut se déplacer que dans quatre directions : nord, ouest, sud et est. Nous supposerons que les chemins qui s'offrent à lui ne le conduiront normalement pas dans un arbre. Il a déjà la gueule de bois, ne l'aggravons pas. Tout au long de son voyage, il tombera sur des objets tels qu'une épée, une hache, de l'or, de l'argent, des diamants, du silex et de l'acier pour allumer un feu, etc. Je ne serai pas assez gentil pour le laisser trouver de l'aspirine, juste parce qu'il doit souffrir un peu pour son laisser-aller de la soirée. Il est également possible qu'il rencontre un monstre ou deux.

Maintenant que nous avons plus ou moins défini son monde, nous allons commencer à écrire du code. Nous devrons créer quelques listes pour gérer les objets du jeu que le joueur peut manipuler et pour « contenir » les objets qu'il a ramassés (ci-dessus).

Our main loop (below) will be fairly simple. As long as the game_running variable is True, then we will continue to loop. At the top of the loop, we ask the user what they want to do and get their response. We send that to the function work_command. Inside the work_command function, we will use the new match case function. We’ll start pretty simply (top right). I’ve defined the global variables here that I think might be used. When we start the match case section, we set the match statement to look at the command that has been split apart with the .split() command. This way, the case statements can look for commands like “quit” as well as “go North” and even things more complicated like “get Axe”. Let’s add another case for moving towards the North.

Notre boucle principale (ci-dessous) sera assez simple. Tant que la variable game_running est True, nous continuons la boucle. Au début de la boucle, nous demandons à l'utilisateur ce qu'il veut faire et obtenons sa réponse. Nous l'envoyons à la fonction work_command.

Dans la fonction work_command, nous utilisons la nouvelle fonction « match case ». Nous allons commencer assez simplement (en haut à droite).

J'ai défini ici les variables globales que je pense pouvoir être utilisées. Lorsque nous démarrons la section match case, nous configurons l'instruction match pour qu'elle regarde la commande qui a été séparée avec la commande .split(). De cette façon, les instructions de cas peuvent rechercher des commandes comme « quitter » ou « vers le Nord » et même des choses plus compliquées comme « prendre hache ». Ajoutons un autre cas pour se déplacer vers le Nord.

case[“North”] | [“go”, “North”]: message = “Ok. Going North” print(message) So in this case (no pun intended), if the user enters the command “North” or “go North”, it will fall into the above case. This allows us to handle multiple options. However, we can even get more complex. In the next version, we can mix the “go” command with an set of directions that will allow us to encapsulate the go command with a direction, use the pattern of ‘North’ | ‘South’ | ‘East’ | ‘West’, assign that to the variable direction, and test that to handle any of the four options.

case[“Nord”] | [“vers”, “Nord”]:

message = “Ok. Vers Nord”

print(message)

Donc, dans ce cas (sans jeu de mots), si l'utilisateur entre la commande « Nord » ou « vers Nord », il tombera dans le cas ci-dessus. Cela nous permet de gérer plusieurs options.

Cependant, nous pouvons même devenir plus complexes. Dans la prochaine version, nous pourrons combiner la commande « go » avec un ensemble de directions qui nous permettra d'encapsuler la commande « go » avec une direction, d'utiliser le modèle « Nord » | « Sud » | « Est » | « Ouest », de l'affecter à la variable « direction » et de la tester pour gérer l'une des quatre options.

Then at the bottom of the test for the four directions, we can make a test, just in case the player decided to get cute, and enter something like “go Up”. The *wth wildcard will catch anything that isn’t part of our four directions. We also can handle things like this (next page, top left). In this instance, the user can type “get Axe” or “pick up Sword” or even “pick shovel up”. So when the program hits this part of the code, the object is then added to the players “bag o’ infinite stuff” by the append command. When the player wants to see the contents of his bag, he just enters “inventory” which displays the contents of the list.

Ensuite, en bas du test pour les quatre directions, nous pouvons faire un test, juste au cas où le joueur déciderait de faire le malin et entrerait quelque chose comme « Monter ». Le caractère générique *wth attrapera tout ce qui ne fait pas partie de nos quatre directions.

Nous pouvons également gérer des choses comme ceci (page suivante, en haut à gauche).

Dans ce cas, l'utilisateur peut taper « prendre hache » ou « ramasser épée » ou même « soulever pelle ». Ainsi, lorsque le programme atteint cette partie du code, l'objet est alors ajouté au « sac d'affaires » du joueur par la commande append. Lorsque le joueur veut voir le contenu de son sac, il lui suffit de taper « inventaire » qui affiche le contenu de la liste.

Pick up Axe ~~~~~~~~~~~~~~~~~~~~~~~~~ You currently have 1 objects in your bag: bag of stuff Axe ~~~~~~~~~~~~~~~~~~~~~~~~~ I have to be honest with you, the examples that I have provided here only scratch the surface of the Structural Pattern Matching feature and are very simplistic. For more information and examples, you can check out the following web sites… https://www.python.org/dev/peps/pep-0636/#adding-conditions-to-patterns https://mathspp.com/blog/pydonts/pattern-matching-tutorial-for-pythonic-code

Ramasser hache ~~~~~~~~~~~~~~~~~~~~~~~~~ Vous avez actuellement 1 objet dans votre sac :

 sac d'affaires
 hache

~~~~~~~~~~~~~~~~~~~~~~~~~

Je dois être honnête avec vous, les exemples que j'ai fournis ici ne font qu'effleurer la surface de la fonction de correspondance des modèles structurels et sont très simplistes. Pour plus d'informations et d'exemples, vous pouvez consulter les sites Web suivants :

https://www.python.org/dev/peps/pep-0636/#adding-conditions-to-patterns

https://mathspp.com/blog/pydonts/pattern-matching-tutorial-for-pythonic-code

As things get a bit further along with the beta version, I’m sure you will see a large amount of web information about all of the version 3.10 features – especially the Pattern Matching feature. I’ll put the Python code that I provided in the article on my github repository at https://github.com/gregwa1953/FCM-168, and I’ll make the text adventure game code closer to usable as a skeleton for you if you want to learn. Until next time, as always; stay safe, healthy, positive and creative!

Au fur et à mesure que les choses avancent dans la version bêta, je suis sûr que vous verrez une grande quantité d'informations sur le web à propos de toutes les fonctionnalités de la version 3.10, en particulier la fonctionnalité de correspondance de motifs.

Je mettrai le code Python que j'ai fourni dans l'article sur mon dépôt github à https://github.com/gregwa1953/FCM-168 (en anglais uniquement), et je rendrai le code du jeu d'aventure textuel plus proche de l'utilisable comme squelette pour vous si vous voulez apprendre.

Jusqu'à la prochaine fois, comme toujours ; restez en sécurité, en bonne santé, positif et créatif !

Encart de la page 25 en bas à droite : Select Case number Case 1 To 5 Debug.WriteLine(“Between 1 and 5, inclusive”) ' The following is the only Case clause that evaluates to True. Case 6, 7, 8 Debug.WriteLine(“Between 6 and 8, inclusive”) Case 9 To 10 Debug.WriteLine(“Equal to 9 or 10”) Case Else Debug.WriteLine(“Not between 1 and 10, inclusive”) End Select

Select Case number Case 1 To 5 Debug.WriteLine(“est entre 1 et 5, inclus”) ' Le suivant est le seul Case évalué à True (Vrai). Case 6, 7, 8 Debug.WriteLine(“est entre 6 et 8, inclus”) Case 9 To 10 Debug.WriteLine(“égal à 9 ou 10”) Case Else Debug.WriteLine(“pas entre 1 et 10, inclus”) End Select

Encart de la page 26 en haut : def check_number(number): match number: case 1 | 2 | 3 | 4 | 5: print(f“{number} is between 1 and 5, inclusive”) case 6 | 7 | 8: print(f“{number} is between 6 and 8, inclusive”) case 9 | 10: print(f“{number} is equal to 9 or 10”) case _: # if none of the above matches. Sort of ‘else’ print(f“{number} Not between 1 and 10, inclusive”) for i in range(0, 12): # get numbers between 0 and 11 check_number(i)

def check_number(number): match number: case 1 | 2 | 3 | 4 | 5: print(f“{number} est entre 1 et 5, inclus”) case 6 | 7 | 8: print(f“{number} est entre 6 et 8, inclus”) case 9 | 10: print(f“{number} est égal à 9 ou 10”) case _: # si aucune correspondance au-dessus. Un peu comme ‘else’ print(f“{number} pas entre 1 et 10, inclus”) for i in range(0, 12): # obtenir les chiffres de 0 à 11 check_number(i)

€ncart page 26 en bas :

if 1 ⇐ number ⇐ 5: print(“Between 1 and 5, inclusive”) elif 6 ⇐ number ⇐ 8: print(“Between 6 and 8, inclusive”) elif number == 9 or number == 10: print(“Equal to 9 or 10”) else: print(“Not between 1 and 10, inclusive”)

if 1 ⇐ number ⇐ 5: print(“entre 1 et 5, inclus”) elif 6 ⇐ number ⇐ 8: print(“entre 6 et 8, inclus”) elif number == 9 or number == 10: print(“égal à 9 ou 10”) else: print(“pas entre 1 et 10, inclus”)

Encart de la page 27 en haut à gauche :

global game_objects, possessions game_objects = ['Axe', 'Hammer', 'Sword', 'flint', 'steel', 'gold', 'silver', 'branch', ''] possessions = ['bag of stuff']

global game_objects, possessions <nowiki>game_objects = ['Hache', 'Marteau', 'Épée', 'Silex', 'Acier', 'Or', 'Argent', 'Branche', '']<:nowiki> possessions = ['Sac d'affaires']

Encart de la page 27 en haut à droite : def work_command(command): global directions, items, monsters, possessions, this_location, game_running global north_count, south_count, east_count, west_count match command.split(): case[“quit”]: print(“Goodbye!”) quit_game()

def work_command(command): global directions, items, monsters, possessions, this_location, game_running global north_count, south_count, east_count, west_count match command.split(): case[“quit”]: print(“Au revoir !”) quit_game()

Encart de la page 27 au milieu à droite : def work_command(command): match command.split(): case 'go', 'North' | 'South' | 'East' | 'West' as direction: match direction: case 'North': print('Moving North') case 'South': print('Moving South') case 'East': print('Moving East') case 'West': print('Moving West') case 'go', *wth: print(f'{wth} is not supported')

def work_command(command): match command.split(): case 'go', 'Nord' | 'Sud' | 'Est' | 'Ouest' as direction: match direction: case 'Nord': print('Vers le Nord') case 'Sud': print('Vers le Sud') case 'Est': print('Vers l'Est') case 'Ouest': print('Vers l'Ouest') case 'go', *wth: print(f'{wth} n'est pas supporté')

Encart de la page 27 en bas à gauche : game_running = True while game_running: response = input('What would you like to do? → ') work_command(response)

game_running = True while game_running: response = input('Que voulez-vous faire ? → ') work_command(response)

Encart de la page 28 : case[“get”, obj] | [“pick”, “up”, obj] | [“pick”, obj, “up”]: if obj in game_objects: print(f“Pick up {obj}”) possessions.append(obj) else: print(f'I do not see the {obj}') case[“inventory”]: print('~'*25) message = f'You currently have {len(possessions)-1} object(s) in your bag:' print(message) for pos in possessions: print(f' {pos}') print(“~“*25)

case[“prendre”, obj] | [“ramasser”, obj] | [“soulever”, obj]: if obj in game_objects: print(f”prendre {obj}”) possessions.append(obj) else: print(f'Je ne vois pas {obj}') case[“inventaire”]: print('~'*25) message = f'vous possédez actuellement {len(possessions)-1} objet(s) dans votre sac :' print(message) for pos in possessions: print(f' {pos}') print(“~“*25)

issue168/python.txt · Dernière modification : 2021/05/07 12:15 de auntiee