[PYTHON] Vous pouvez utiliser les décorateurs assert et Enum (ou) pour vérifier la conformité aux contraintes d'annotation de type sans l'aide de mypy.

0. Introduction

Pour la vérification de type Python3, la saisie et mypy sont connus.


Article Qiita de @ Mski_iksm «Vérification de type de python à l'aide de l'indice de type et de mypy»Article Qiita de @ Papi_tokei "Practice !! Introduction to Python type (Type Hints)"SWEet "Let's type check with Python"Blog de Mizzsugar "La première étape de l'apprentissage des génériques avec Python et TypeScript"


__ Ce * mypy * vérifie si la contrainte d'annotation de type est suivie de l'extérieur du fichier de script Python. __

Vous pouvez utiliser l'instruction __ * assert * et le type d'énumération * Enum * pour vérifier le type et la valeur des arguments de méthode et renvoyer les valeurs sous une forme fermée (autonome) dans le fichier de script. __

__ La même chose peut être implémentée en utilisant des décorateurs. __

1. Comment utiliser * assert * et * Enum *

(Référence)

Note.nkmk.me "fonction de type pour obtenir / déterminer le type avec Python, fonction isinstance" ・ [CodeZine "Explication de l'utilisation de la fonction" Assertion "qui est vraiment utile en Python! Tiré de "Python Trick"]](https://codezine.jp/article/detail/12179) ・ Qu'est-ce qu'une déclaration d'assertion?

(Problème de réglage)

  1. Utilisez * spacy * pour extraire des mots "propriétaires" spécifiques d'une phrase. Lorsque plusieurs mots appartenant à "l'expression unique" spécifiée sont trouvés, le nombre de fois où chaque mot apparaît dans la phrase est compté et les mots sont renvoyés dans l'ordre de fréquence d'apparition.
  2. Il y a une limite aux types (étiquettes) des "expressions uniques" que * spacy * peut reconnaître.
  3. L'utilisateur passe en argument le mot "expression unique" qu'il souhaite extraire de la phrase.
  4. La méthode prend deux arguments. Le premier est la phrase à analyser (doit être de type * str *), et le second est le libellé (nom) de "l'expression unique".
  5. Si les données texte passées en argument ne sont pas de type * str *, une erreur est renvoyée. De plus, si le nom d'étiquette "expression unique" passé comme argument n'est pas trouvé dans l'étiquette "expression unique" définie, une erreur est renvoyée.

Python3


from enum import Enum
from typing import List, Dict
import spacy

class NamedEntityLabel(Enum):
	Jinmei : str = "PERSON"
	Chimei : str = "LOC"

	def extract_named_entity_wordlist(text : str, ne_label : str) -> List[str]:
		#Vérifiez le type du premier argument
		assert type(text) is str, 'Les données textuelles que vous entrez doivent être une chaîne.'
		#Vérifiez la valeur du deuxième argument
		right_value_list = [e.name for e in NamedEntityLabel]
		assert ne_label in right_value_list, 'Le libellé d'expression unique entré n'a pas encore été défini.'
		#S'il n'y a pas de problème avec le type et la valeur des deux arguments reçus, exécutez ce qui suit
    	nlp = spacy.load('ja_ginza')
   	 	text = text.replace("\n", "")
    	doc = nlp(text)
    	word_list = [ent.text for ent in doc.ents if ent.label_ == NamedEntityLabel[ne_label].value]
    	return word_list
    	

politique

Vous pouvez écrire __ * if ne_label pas dans ["PERSON", "LOC"] , mais ici, afin de décrire explicitement le "type d'expression unique prédéfini" dans le code, la "classe d'expression unique" Est défini par le type d'énumération ( Enum *). __

Essayez d'utiliser

(Lorsque la valeur prévue est passée en argument)

__ Extrayez les mots correspondant à l'étiquette d'expression unique spécifiée de la phrase * text * reçue et retournez chaque mot dans l'ordre de fréquence d'occurrence. (Extraction d'expression unique: * Reconnaissance d'entité nommée *) __

Python3


text = """Aujourd'hui, je suis venu en Amérique avec Mary. Je suis passé par Paris, France."""
 
NamedEntityLabel.extract_named_entity_wordlist(text, "Chimei")
#résultat
['Amérique', 'France', 'Paris']

NamedEntityLabel.extract_named_entity_wordlist(text, "Jinmei")
#résultat
['Marie']

(Lorsqu'une valeur involontaire est passée en argument)

Python3


NamedEntityLabel.extract_named_entity_wordlist(text, "Soshikimei")
#résultat
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in extract_named_entity_wordlist
AssertionError:Le libellé d'expression unique entré n'est pas encore défini

Python3


NamedEntityLabel.extract_named_entity_wordlist(127, "Soshikimei")
#résultat
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in extract_named_entity_wordlist
AssertionError:Les données textuelles que vous entrez doivent être une chaîne.

Python3


NamedEntityLabel.extract_named_entity_wordlist(127, "Jinmei")
#résultat
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in extract_named_entity_wordlist
AssertionError:Les données textuelles que vous entrez doivent être une chaîne.

Vous pouvez également utiliser des décorateurs comme la page Web ci-dessous.

Ensuite, voyons comment utiliser le décorateur.

2. Comment utiliser Decorator et * Enum * sans utiliser * assert *

Python3


class NamedEntityLabel(Enum):
	Jinmei : str = "Person"
	Chimei : str = "LOC"
	Soshikimei :str = "ORG"
    @classmethod
    def value_check(cls, target_value):
        for e in NamedEntityLabel:
            if e.name == target_value:
                return e
        raise ValueError('{}N'est pas une étiquette d'expression unique définie'.format(target_value))

(Comment utiliser)

Python3


NamedEntityLabel.value_check("Jinmei")

#Résultat d'exécution
NamedEntityLabel.value_check("Jinmei")
<NamedEntityLabel.Jinmei: 'Person'>

Python3


NamedEntityLabel.value_check("EmailAddress")

#Résultat d'exécution
ValueError:EmailAddress n'est pas une étiquette d'expression unique définie

Créez le code suivant en utilisant ce qui précède

Python3


class NamedEntityLabel_2(Enum):
	Jinmei : str = "PERSON"
	Chimei : str = "LOC"
    @classmethod
    def value_check(cls, target_value):
        for e in NamedEntityLabel_2:
            if e.name == target_value:
                return e
        raise ValueError('{}N'est pas une étiquette d'expression unique définie
'.format(target_value))
        
	def extract_named_entity_wordlist(text : str, ne_label : str) -> List[str]:
		#Vérifiez le type du premier argument
		assert type(text) is str, 'Les données textuelles que vous entrez doivent être une chaîne.'
		#Vérifiez la valeur du deuxième argument
		e = NamedEntityLabel_2.value_check(ne_label)
		#S'il n'y a pas de problème avec le type et la valeur des deux arguments reçus, exécutez ce qui suit
    	nlp = spacy.load('ja_ginza')
   	 	text = text.replace("\n", "")
    	doc = nlp(text)
    	word_list = [ent.text for ent in doc.ents if ent.label_ == e.value]
    	return word_list

(Lorsque la valeur prévue est passée en argument)

Python3


text = """Aujourd'hui, je suis venu en Amérique avec Mary. Je suis passé par Paris, France."""
 
NamedEntityLabel_2.extract_named_entity_wordlist(text, "Chimei")
#résultat
['Amérique', 'France', 'Paris']

(Lorsqu'une valeur involontaire est passée en argument)

Python3


NamedEntityLabel_2.extract_named_entity_wordlist(text, "Soshikimei")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 12, in extract_named_entity_wordlist
  File "<stdin>", line 9, in value_check
ValueError:Soshikimei n'est pas une étiquette d'expression unique définie

Python3


NamedEntityLabel_2.extract_named_entity_wordlist(127, "Soshikimei")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 11, in extract_named_entity_wordlist
AssertionError:Les données textuelles que vous entrez doivent être une chaîne.

(Référence)

Le code pour vérifier si la contrainte d'annotation du type de méthode est respectée à l'aide du décorateur est également proposé sur la page Web suivante.

Blog CosmoSonic21 "Implémentation de la vérification du type d'argument de fonction avec un décorateur en Python"


3. Comment utiliser l'instance de classe * Enum * créée en passant l'argument reçu au constructeur dans le traitement du corps principal

Ce qui suit est le plus simple.

( Méthode )

  1. Transmettez le nom d'étiquette d'expression unique reçu au constructeur d'instance de la classe de type d'énumération (où l'expression unique est définie) pour créer une instance de la classe d'expression unique.
  2. Le traitement des données utilise l'instance générée de la classe d'expression unique.
  3. Si une étiquette d'expression unique non définie est reçue, une erreur de clé se produira au stade de la création d'une instance de la classe d'expression unique et aucun autre traitement ne sera effectué.

__ Tout d'abord, transmettez un nom d'étiquette d'expression unique approprié au constructeur et vérifiez ce qui se passe lorsque vous essayez de créer une instance de la classe de type d'énumération (où l'expression unique est définie). __

__ Déclaration de classe de type énumération (* Enum *) __

Python3


from enum import Enum
import enum
from typing import List, Dict

@enum.unique
class NamedEntityLabel(Enum):
Jinmei : str = "PERSON"
Chimei : str = "LOC"

__ Passez des données arbitraires au constructeur pour créer une instance de la classe de type énumération (* Enum *) __

__ (Si la valeur transmise est * Name * défini dans la classe * Enum *) __ __ L'instance a été créée avec succès __

Python3


named_entity_instance_test = NamedEntityLabel["Jinmei"]
print(named_entity_instance_test)
#Résultat de l'exécution: l'instance a été créée avec succès
NamedEntityLabel.Jinmei
#Extraire le nom de l'instance générée
print(named_entity_instance_test.name)
#Résultat d'exécution
Jinmei
#Extraire la valeur de l'instance générée
print(named_entity_instance_test.value)
#Résultat d'exécution
PERSON

__ (Si la valeur transmise est * Nom * non défini dans la classe * Enum *) __ __ Aucune instance n'est créée et j'obtiens une erreur __

Python3


named_entity_instance_test = NamedEntityLabel["EMAIL"]
#Résultat de l'exécution: une erreur s'est produite car un nom non défini a été passé dans la classe NamedEntityLabel (type d'énumération type Enum).
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/ocean/.pyenv/versions/3.9.0/lib/python3.9/enum.py", line 355, in __getitem__
    return cls._member_map_[name]
KeyError: 'EMAIL'

__ (Si la valeur transmise est * Name * défini dans la classe * Enum *) __ __ L'instance a été créée avec succès __

Python3


#Variables passées au constructeur lors de la création d'une instance de la classe NamedEntityLabel
#Cette variable suppose le cas du stockage de la valeur reçue de l'utilisateur
input_data_ok = "Jinmei"
input_data_ng = "Emailaddress"

named_entity_instance_ok = NamedEntityLabel[input_data_ok]
#Pas d'erreur
print(named_entity_instance_ok)
#Résultat de l'exécution: l'instance a été créée avec succès
NamedEntityLabel.Jinmei
#Extraire le nom de l'instance générée
print(named_entity_instance_ok.name)
#Résultat d'exécution
Jinmei
 
#Extraire la valeur de l'instance générée
print(named_entity_instance_ok.value)
#Résultat d'exécution
PERSON

__ (Si la valeur transmise est * Nom * non défini dans la classe * Enum *) __ __ Aucune instance n'est créée et j'obtiens une erreur __

Python3


named_entity_instance_ng = NamedEntityLabel[input_data_ng]
#Résultat de l'exécution: une erreur s'est produite car un nom non défini a été passé dans la classe NamedEntityLabel (type d'énumération type Enum).
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/ocean/.pyenv/versions/3.9.0/lib/python3.9/enum.py", line 355, in __getitem__
    return cls._member_map_[name]
KeyError: 'Emailaddress'

Après avoir reçu ce qui précède, réécrivez le script entier __

Article Qiita de @ Ksato9700 "Nouveautés de Python 3.4.0 (2) --enum"

(1) Définir la classe * Enum *

__ Définissez ce qui est disponible en tant que nom d'étiquette d'expression unique en tant que classe d'énumération __

Python3


class NamedEntityLabel_3(Enum):
    Jinmei : str = "PERSON"
    Chimei : str = "LOC"

(2) Définir une méthode pour traiter le corps principal

__ Faites attention aux deux lignes suivantes __

-Utilisation d'une instance de la classe NamedEntityLabel

__ (1ère place) __ named_entity_instance = NamedEntityLabel_3[ne_label]

__ (2ème place) __ word_list = [ent.text for ent in doc.ents if ent.label_ == named_entity_instance.value]

Python3


def extract_named_entity_wordlist(text : str, ne_label : str) -> List[str]:
	#Vérifiez le type du premier argument
    assert type(text) is str, 'Les données textuelles que vous entrez doivent être une chaîne.'
    #Vérifiez la valeur du deuxième argument
    #Si le mot reçu en tant qu'argument est un mot non défini comme nom de la classe NamedEntityLabel, une erreur Key se produit si vous essayez de transmettre ce mot au constructeur pour générer une instruction pour NamedEntityLabel.
    named_entity_instance = NamedEntityLabel_3[ne_label]
    #S'il n'y a pas de problème avec le type et la valeur des deux arguments reçus, exécutez ce qui suit
    nlp = spacy.load('ja_ginza')
    text = text.replace("\n", "")
    doc = nlp(text)
    word_list = [ent.text for ent in doc.ents if ent.label_ == named_entity_instance.value]
    return word_list

(Lorsque la valeur prévue est passée en argument)

Python3


extract_named_entity_wordlist(text, "Chimei")
#Résultat d'exécution
['Amérique', 'France', 'Paris']

(Lorsqu'une valeur involontaire est passée en argument)

Python3


extract_named_entity_wordlist(text, "Soshikimei")
#Résultat d'exécution
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in extract_named_entity_wordlist
  File "/Users/ocean/.pyenv/versions/3.9.0/lib/python3.9/enum.py", line 355, in __getitem__
    return cls._member_map_[name]
KeyError: 'Soshikimei'

-Une paire de __unique expression label name (Name) et value (Value) peut être définie comme une paire de * key * et * value * dans un objet de type dictionnaire (* dict * type). -Cependant, ici, afin de décrire explicitement le "type d'expression unique prédéfini" dans le code, une classe appelée "classe d'expression unique" est définie comme un type d'énumération (* Enum *). __

Recommended Posts

Vous pouvez utiliser les décorateurs assert et Enum (ou) pour vérifier la conformité aux contraintes d'annotation de type sans l'aide de mypy.
Vous pouvez également vérifier la communication de la base de données et du cache avec curl
Anglais technique> vous utilisez les opérateurs booléens [et, ou, et non] pour ...> Opérations booléennes - et, ou, non
Utilisez bash-completion pour taper de longues commandes sans regarder man ou help
Vérifiez le type de variable que vous utilisez
J'ai essayé de vérifier à l'aide du réseau neuronal si «japonais» uniquement «polices illisibles» ne peuvent vraiment être lus que par le japonais
Notes de site pour vous aider à utiliser NetworkX avec Python
Vérifiez le type et la version de la distribution Linux