Je suis tombé sur différents points en utilisant Python, mais voici quelques conseils que j'aurais dû connaître avant de commencer à écrire afin d'éviter de tels pièges et d'avoir une vie Python confortable.
Il existe 2 séries et 3 séries en Python, et la série 3 a des changements qui affectent la compatibilité descendante. Autrement dit, le code Python3 peut ne pas fonctionner dans Python2 (et vice versa).
Python3 a amélioré divers points dans Python2, et si vous l'utilisez à partir de maintenant, c'est essentiellement fait avec la dernière version de Python3 (également ci-dessous, j'ai spécifié ce qui sera amélioré avec Python3). Mieux encore, Python2 est fin du support au 1er janvier 2020. Il n'y a donc aucune raison d'utiliser Python 2 à partir de maintenant. Ceux qui utilisent encore Python 2 sont renvoyés par les élèves du primaire.
Cependant, il existe certains packages qui ne sont pas encore compatibles avec Python3, et que vous puissiez ou non atteindre un tel package dans votre propre projet est un tournant dans votre destin. Vous pouvez vérifier l'état du support dans une liste à partir de ici. Cependant, je pense que la plupart des packages sont déjà pris en charge ou peuvent être exécutés avec Python3 [Il existe également une conversion automatique de 2 à 3](http://docs.python.jp/2/library/2to3. html). Au contraire, s'il ne supporte pas Python3, on peut dire que l'état de maintenance doit être mis en doute. Google App Engine est également enfin compatible avec Python 3 dans la deuxième génération. Même OpenAI, un institut de recherche de premier plan sur l'intelligence artificielle, est passé à Python 3, donc ceux qui disent que "l'apprentissage automatique n'est pas encore ..." ne sont pas au moins avancés. Étant humain, vous n'avez pas à vous fier à ce que vous dites.
Lors du développement de Python, il est presque essentiel d'installer pip et virtualenv en plus de Python lui-même, voici donc un résumé de la configuration de Python, pip et virtualenv dans chaque environnement.
Je pense qu'il y a de nombreuses raisons pour lesquelles je veux faire de l'apprentissage automatique comme raison de choisir Python, donc je vais d'abord présenter la méthode pour cela. Pour créer un environnement d'apprentissage automatique, nous vous recommandons d'utiliser Miniconda, qu'il s'agisse de Mac / Linux / Windows.
La méthode d'installation est celle indiquée sur la page ci-dessus. Miniconda a une fonction pour créer un environnement (environnement virtuel) pour chaque application, et il est facile d'installer des packages liés à l'apprentissage automatique. De plus, cuda requis pour le GPU et mingw, qui est un environnement de build Windows, peuvent être installés. C'est possible, et il est facile d'introduire des outils autres que de simples packages. Pour TensorFlow, les outils autour du GPU seront installés en installant avec conda, et la version CPU fonctionnera à grande vitesse (Détails. tensorflow-in-anaconda /)).
Après avoir installé Miniconda, vous pouvez créer un environnement d'apprentissage automatique général tel que scikit-learn sur Jupyter Notebook avec la commande suivante.
conda create -n ml_env numpy scipy scikit-learn matplotlib jupyter
activate ml_env
Un environnement appelé ml_env
est créé avec conda create
, et il est activé avec ʻactivate. Pour plus de détails sur l'utilisation de la commande
conda`, reportez-vous à here (elle ne démarre pas pour Windows / Powershell. Pour plus de détails, voir [section Windows] ](Https://qiita.com/icoxfog417/items/e8f97a6acad07903b5b0#windows%E3%81%AE%E5%A0%B4%E5%90%88) Référence).
L'environnement de Miniconda est également fourni dans Dockerfile
, et vous pouvez facilement créer un conteneur en l'héritant avec FROM continuumio / miniconda3
etc.
Si vous souhaitez partager un environnement d'apprentissage automatique avec un conteneur Docker, ou si vous envisagez de le déployer dans un environnement PaaS tel que Heroku, nous vous recommandons d'envisager d'utiliser Docker ([Heroku prend en charge docker push avec la fonction Container Registry. [Https://devcenter.heroku.com/articles/container-registry-and-runtime).
Anaconda n'est pas recommandé comme environnement d'apprentissage automatique pour les deux raisons suivantes.
Notez que même avec Miniconda, si vous ne supprimez pas régulièrement les paquets inutilisés avec conda clean --all
, vous pourrez prendre quelques G à la légère **. C'est parce que conda stocke les paquets qui ont été téléchargés une fois en tant que cache. Même les anciens packages qui ne sont pas utilisés actuellement resteront tant qu'ils ne seront pas supprimés, il est donc bon de les supprimer.
Python est inclus par défaut, mais il peut ne pas correspondre à la version que vous souhaitez développer. Par conséquent, il est bon d'utiliser pyenv pour changer la version de Python utilisée pour chaque projet. Cependant, comme mentionné ci-dessus, si vous utilisez Miniconda, vous pouvez gérer la version de Python ici, vous n'avez donc pas besoin d'installer pyenv. De plus, lors de l'utilisation de Miniconda, il est préférable de ne pas installer pyenv car la commande au bâton se produit et le shell se bloque lors de l'activation de l'environnement virtuel (ʻactivate`).
pyenv install x.x.x
. Ensuite, définissez le Python à utiliser avec pyenv global x.x.x
Python utilisé dans chaque projet est défini dans pyenv local x.x.x
.
Après avoir installé un nouvel environnement Python avec pyenv, pyenv rehash
est requis. Si vous ne trouvez toujours pas l'installation, essayez de redémarrer le terminal.
Vous pouvez l'installer normalement, mais nous vous recommandons Miniconda.
Veuillez noter qu'à partir de 2018, [ʻactivatene démarre pas encore dans PowerShell](https://github.com/conda/conda/issues/626). Si vous ne voulez pas passer à
cmd à chaque fois, vous pouvez l'utiliser en installant
pscondaenvs (ce qui suit est le cas de l'installation dans l'environnement global (
root`)).
conda install -n root -c pscondaenvs pscondaenvs
La gestion des packages est introduite pour installer des bibliothèques et un environnement virtuel est introduit pour isoler la version Python et les bibliothèques à utiliser pour chaque projet.
Puisque pip
est installé en standard à partir de Python 3.4, il n'est pas nécessaire de l'installer séparément pour le moment. Si vous utilisez l'ancien Python, installez-le avec get_pip.py.
virtualenv
peut être installé avec pip install virtualenv
.
Cependant, officiellement, il est recommandé d'utiliser Pipenv qui inclut la fonction de pip / virtualenv. Avec Pipenv, comme npm dans Node.js, il est facile d'écrire des bibliothèques dépendantes en même temps que l'installation, et de séparer les bibliothèques d'installation de développement / production.
Le développement Python est généralement effectué par la configuration suivante.
Une fois réécrit en tant que commande, il a la forme suivante. Nous présenterons trois cas lors de l'utilisation du nouveau pipenv, lors de l'utilisation du pip / virtualenv conventionnel et lors de l'utilisation de conda.
Dans pipenv
, il n'est pas nécessaire de demander explicitement la création d'un environnement virtuel. Si vous installez avec pipenv install
, il créera un environnement virtuel et l'installera ici. Cependant, il est créé dans un chemin qui n'est pas bien compris par défaut et il est difficile de bénéficier des avantages du stockage de code dans un environnement de développement intégré tel qu'il est.
Par conséquent, il est préférable de définir PIPENV_VENV_IN_PROJECT = 1
(ou true
) avant utilisation. En faisant cela, un environnement virtuel sera construit dans .venv
du dossier actuel.
# 1.Créer un dossier de projet
mkdir myproject
cd myproject
# 2.Installez les bibliothèques requises avec pipenv
pipenv install xxxx
##Bibliothèque utilisée uniquement pour le développement(Bibliothèques utilisées pour les tests, etc.)À`-dev`Mettez
pipenv install --dev xxxx
##La bibliothèque installée par pipenv est automatiquement Pipfile.Écrit pour verrouiller. Si vous souhaitez le charger et l'installer, lancez simplement pipenv install
pipenv install
# 3.Exécuter
pipenv run python xxx.py
##Si vous souhaitez démarrer le shell, utilisez pipenv shell
pipenv shell
#Lors de la suppression de l'environnement créé,
pipenv --rm
# 1.Créer un dossier de projet
mkdir myproject
cd myproject
# 2.Création d'un environnement virtuel venv est un nom de dossier et l'environnement du projet est préparé ici
virtualenv venv
# 3.Activez l'environnement virtuel et installez les modules requis avec pip
#Pour Windows, venv/Scripts/activate.bat De plus, si vous utilisez le shell de Git, vous pouvez le faire avec source de la même manière
#Notez que si vous n'activez pas l'environnement virtuel, il sera installé globalement, alors désactivez-le.
source venv/bin/activate
pip install xxxx
#Liste créée par pip freeze(requirements.txt)Lors de l'installation depuis
pip install -r requirements.txt
# 4.Exécuter
python xxx.py
# 1.Créer un environnement virtuel(quelque chose comme virtualenv)
conda create -n my_env numpy scipy
##Afficher une liste d'environnements virtuels
conda info -e
# 2.Activer l'environnement virtuel
activate my_env # Windows
source activate my_env # Max/Linux
##Installation supplémentaire dans un environnement virtuel(Lors de la spécification de la version conda install scipy=0.12.0 etc.)
conda install scikit-learn
##Installer avec pip pour les choses qui ne peuvent pas être obtenues avec conda(Support en mettant pip dans l'environnement virtuel)
conda install pip
pip install Flask
##Mise à jour des packages installés(conda lui-même est conda mise à jour conda)
conda update numpy
# 3.Exportez l'environnement construit avec conda/Lis
conda env export > environment.yml
conda env create -f environment.yml
# 4.Désactiver l'environnement virtuel
deactivate # Windows
source deactivate # Max/Linux
Voir ici pour plus de détails.
Les dossiers d'environnement virtuel ci-dessus (venv, etc.) et les fichiers .pyc
doivent être exclus pour la gestion des versions.
Le fichier .pyc
est un fichier pour accélérer l'exécution, et une fois exécuté, un fichier est créé pour chaque fichier. Si vous mettez cela dans la gestion des versions, le fichier sera doublé, vous devez donc le supprimer (vous pouvez également ajouter l'option -B ou définir la variable d'environnement PYTHONDONTWRITEBYTECODE pour empêcher sa génération. Can (référence)).
Pour les autres fichiers qui doivent être ignorés, reportez-vous à Python .gitignore.
Tips
De plus, en fonction de la bibliothèque, il y en a qui ne peuvent pas être entrés docilement avec pip install
. Cela se remarque sous Windows. Dans de nombreux cas, cela peut être évité par conda install
, mais si le problème persiste, prenez les mesures suivantes.
pip install <file_path>
(à part) Toutefois, à l'aide de wheel, les bibliothèques dépendantes peuvent être incluses dans le référentiel dans un état compilé. Cela évite que l'installation de pip ne puisse être effectuée dans l'environnement de l'autre partie lors de la distribution et du déploiement. Pour plus de détails Référence du document).Maintenant que l'environnement de développement Python est en place, voici quelques points à garder à l'esprit lors du développement avec Python, qui est le sujet principal.
Veuillez noter que si vous n'ajoutez pas ce qui suit au début de chaque fichier, les caractères japonais seront déformés. Comme mentionné dans here, c'est une bonne idée de toujours le mettre au début du fichier.
# -*- coding: utf-8 -*-
En Python3, le codage par défaut est UTF-8, donc ce support est inutile (PEP 3120 --Utilisation de UTF-8 comme codage source par défaut. / dev / peps / pep-3120 /)).
Comme mentionné ci-dessous, s'il est supposé que Python 2/3 sera pris en charge, et si vous souhaitez bénéficier des avantages de Python 3 (en particulier l'unification Unicode), vous devez également importer les éléments suivants ([here](http: http :). //methane.hatenablog.jp/entry/2014/01/18/Python_2/3_%E4%B8%A1%E5%AF%BE%E5%BF%9C%E3%81%AE%E3%81%9F% E3% 82% 81% E3% 81% AB_% 60unicode_literals% 60_% E3% 82% 92% E4% BD% BF% E3% 81% 86% E3% 81% B9% E3% 81% 8D% E3% 81% 8B) Référence).
from __future__ import division, print_function, absolute_import, unicode_literals
Python a un guide de codage officiellement défini (PEP8) (original/ [traduction en japonais](http: //) pep8-ja.readthedocs.io/ja/latest/)), de nombreux environnements de développement intégrés permettent de vérifier en utilisant ceci.
C'est pratique car vous pouvez vérifier en détail les points tels que le trop grand nombre de sauts de ligne et la présence de caractères vides, et vous pouvez corriger les points que vous avez négligés. Au contraire, si vous ne le mettez pas depuis le début, il sera difficile de le réparer plus tard, alors mettons-le lors de la configuration de l'environnement.
Comme son nom l'indique, le package pep8 qui vérifie la conformité PEP8 n'est actuellement pas maintenu [pycodestyle](https: //). Veuillez noter qu'il s'agit de github.com/PyCQA/pycodestyle) (Le contexte est qu'il est difficile de savoir si le nom du package "pep8" est une convention ou un outil, donc Renommé Parce qu'il a été suggéré).
Si vous souhaitez ne conserver que les vérifications logiques (importations inutiles, variables inutilisées, etc.) avec pep8, pycodestyle qui vérifie pep8 et pyflakes qui effectuent des vérifications logiques sont emballés [flake8](http: //: flake8.pycqa.org/en/latest/) est recommandé. Pylint peut être vérifié de différentes manières, mais il existe de nombreuses scènes qui peuvent être ennuyeuses, et il est nécessaire de payer un coût raisonnable pour le régler à un niveau approprié.
Par conséquent, je voudrais d'abord recommander le chemin de flake8, puis passer à Pylint lorsqu'il est nécessaire d'améliorer la norme de codage.
Python est livré en standard avec ʻunittest` (http://docs.python.jp/2/library/unittest.html), il n'est donc pas nécessaire d'ajouter un package pour les tests unitaires.
ʻUnittest2` ressemble à un nouveau framework, mais comme il s'agit d'utiliser le framework de test unitaire pour la nouvelle version de l'ancienne version, il n'est fondamentalement pas nécessaire de l'introduire (en aparté, j'ai donné ce numéro) J'aimerais que vous arrêtiez d'utiliser le nom du package, tel que urllib2).
En Python, la chaîne de caractères normale str
et la chaîne de caractères Unicode ʻunicode` sont séparées.
str = "abc" # An ordinary string
uni_str = u"abc" # A Unicode string
En interne, il n'y a pas beaucoup de problème avec str tel quel, mais lorsque des entrées externes / sorties externes telles que des applications Web sont impliquées, il est préférable de s'unifier avec unicode (lors de l'utilisation d'un framework, lequel Vous devez savoir s'il arrive ou si vous devez transmettre la valeur).
En Python3, il est unifié en unicode. De plus, en Python2, il peut être unifié en ʻunicode en utilisant
from future import unicode_literals`.
Dans le système Python2, le résultat de la division entre des entiers tels que 1/3 ne devient pas de type float.
>>> 1/3
0
>>> 3/2
1
Ceci est résolu dans Python3 (dans l'exemple ci-dessus, cela devient un résultat d'opération arithmétique normal tel que 0,333 ..., 1,5). Si vous souhaitez rendre Python2 identique à Python3, vous pouvez le résoudre en effectuant l'importation suivante au début.
from __future__ import division
De plus, il y a aussi un signe «//» en division. À première vue, cela semble être un opérateur pour faire un quotient, mais ce n'est pas le cas. Strictement parlant, l'opération par «//» est la «valeur entière maximale qui ne dépasse pas le résultat du calcul». Par exemple, si 3 est divisé par 2, ce sera 1,5 et le nombre entier maximum qui ne dépasse pas ce sera 1. C'est aussi bon qu'un quotient, mais le problème est lorsque la valeur est négative.
>>> -3 / 2
-2
Le résultat change simplement parce que le signe devient négatif. Qu'est-ce que c'est ça? Vous pourriez penser, mais s'il est négatif, l'entier maximum qui ne dépasse pas -1,5 est «-2», qui est une spécification, pas un bogue. Et cette spécification est la même en Python3.
Par conséquent, si vous souhaitez calculer le quotient en toute sécurité, il est préférable de calculer de sorte que le résultat soit flottant et tronqué après la virgule décimale. Pour Python3, cela tronque simplement le résultat calculé par /
.
Il existe une fonction intégrée appelée divmod
qui calcule le quotient et le reste en même temps, mais soyez prudent car le" quotient "dans cette fonction est le même que le résultat du calcul de //
(tant que le document dit "quotient". , Je pense que c'est un bug, mais ...).
Le processus «round», qui consiste à arrondir en Python, est l'arrondi bancaire (également appelé arrondi au nombre pair le plus proche, arrondi JIS et arrondi ISO). Plus précisément, lorsque le nombre après la virgule décimale est "0,5", il est rapproché d'un nombre pair. C'est un processus qui est effectué car si 0,5 est toujours arrondi à un plus, la valeur du total après arrondi (arrondi au supérieur) sera plus grande dans le total avant et après arrondi = il y aura un biais ( Voir Traitement des fractions de Wikipedia (https://ja.wikipedia.org/wiki/%E7%AB%AF%E6%95%B0%E5%87%A6%E7%90%86) pour plus de détails).
>>> round(3 / 2)
2
>>> round(1 / 2)
0
Puisque «1/2 = 0,5», je pense que c'est 1, mais c'est une histoire d'arrondi arithmétique, et dans le cas de l'arrondi bancaire, comme mentionné ci-dessus, il est arrondi à «même le plus proche de 0,5», c'est-à-dire à 0. Notez que ** Python2 est une arithmétique arrondie, alors soyez prudent **.
Les autres langages utilisant l'arrondi bancaire incluent C # (voir [ici](https://qiita.com/nekonenene/items/05b85048feb05a6bb9ee#%E4%B8%80%E8%A6%] Voir A7% E8% A1% A8)).
Dans la déclaration de classe bien présentée ci-dessous, il s'agit d'une classe de style ancien.
class MyClass():
pass
Qu'est-ce qui est différent de la classe de style ancien? Il y a beaucoup de choses, mais au moins créer avec l'ancienne classe de style n'a plus aucun mérite.
Dans l'ancienne classe de style, super
qui appelle la classe parente ne fonctionne pas, donc je ne sais pas à quoi sert l'héritage.
Par conséquent, la classe est déclarée comme suit.
class MyClass(object):
pass
Cela signifie hériter de «objet». Depuis Python3, ce sera une nouvelle classe de style par défaut l'ancienne classe de style sera supprimée.
Python 3 simplifie également le processus d'appel de la classe parent. En Python2, c'était une méthode d'appel compliquée telle que super (nom de la classe enfant, self) .parent_method ()
, mais en Python3, elle peut être appelée normalement avec super (). Parent_method ()
.
L'héritage est possible, mais il n'existe aucun mécanisme pour forcer l'implémentation à des classes inférieures. Cependant, abc a été ajouté en standard à partir de Python 2.6, et il est devenu possible d'implémenter une pseudo classe abstraite (abc est une abréviation de classe de base abstraite).
from abc import ABCMeta
class MyABC:
__metaclass__ = ABCMeta
def describe(self):
print("I'm abc")
@abstractmethod
def must_implements(self):
pass
En Python3, vous pouvez utiliser metaclass
lors de la création d'une classe, afin de pouvoir l'écrire plus simplement.
from abc import ABCMeta
class MyABC(metaclass=ABCMeta):
...
Vous pouvez également enregistrer une classe qui utilise register
sous votre contrôle (sous-classe). Cependant, comme il "lui donne simplement l'apparence", tuple n'est pas réellement une classe héritée de MyABC même dans l'exemple suivant, et les méthodes réellement implémentées dans MyABC ne peuvent pas être utilisées.
MyABC.register(tuple)
assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)
().describe() # Attribute Error
Même s'il est vrai dans «cette instance», il semble déroutant d'obtenir une erreur d'attribut dans la méthode, donc je ne peux pas vraiment imaginer la scène d'utilisation. Je pense qu'il vaut mieux en hériter normalement. Bien sûr, une méthode qui déclare normalement une classe et est forcée de l'implémenter lève une exception dans la classe parente.
Python sera l'un des rares langages à prendre en charge l'héritage multiple.
class MultiInheritance(Base1, Base2, Base3):
...
La solution se fait dans l'ordre à partir de la gauche, et dans ce qui précède, si ce n'est pas en soi, Base1 est recherchée, puis Base2, et ainsi de suite. super est la classe la plus à gauche lorsqu'elle est appelée normalement.
Comme mentionné ci-dessus, Python n'a pas d'interface, il utilisera donc à la place l'héritage multiple (ou Module / Mix-in). Je pense qu'il vaut mieux ne pas utiliser l'héritage multiple à d'autres fins. Cependant, puisque tout le monde ressemble à une classe, il est préférable de décider de la règle du nom de la classe telle que commencer par ʻI` pour celle à utiliser comme interface (ou créer une classe telle que Interface / Module et en hériter).
En Python, «new» et «init» sont tous deux des constructeurs, n'est-ce pas? Il y a deux fonctions qui ressemblent à.
En gros, utilisez «init».
Cependant, comme vous pouvez le voir à partir de l'argument self
, __init __
est un "processus d'initialisation après la création de l'instance", pas strictement un constructeur. __new__
est le processus de retour de l'instance pour l'initialisation avec __init__
. Si vous voulez le faire, vous pouvez renvoyer une instance autre que votre propre classe, mais le mérite n'est pas si grand. Est-il utilisé pour l'implémentation singleton?
Les instances Python ont des attributs cachés entourés de deux traits de soulignement, comme le __init __
ci-dessus (également dans la définition de classe / fonction elle-même).
Celles-ci sont utilisées pour stocker des méta-informations et effectuer des opérations de base (telles que le comportement lors de la définition / récupération de valeurs dans les attributs).
Les détails sont détaillés dans Modèle de données, mais ceux qui sont souvent utilisés / utiles sont les suivants.
Nom d'attribut | Contenu |
---|---|
__class__ |
Définition de classe.__class__.__name__ Vous pouvez obtenir le nom de la classe avec |
__dict__ |
Tous les attributs(Y compris la méthode)dictionnaire |
__doc__ |
De classes et de méthodesdocstringPeut être obtenu. Si vous ne savez pas comment l'utiliser, mais qu'il est difficile de trouver le code source ou la documentation de l'API, vous pouvez le voir rapidement. |
Nom de la méthode | Contenu |
---|---|
__getattr__ |
Appelé lorsque l'accès à l'attribut est effectué et que l'attribut cible n'existe pas |
__getattribute__ |
Toujours appelé lors de l'accès aux attributs |
__setattr__ |
Appelé lors de l'attribution à un attribut |
__delattr__ |
Appelé lors de la suppression d'un attribut(del obj.xxx ) |
__getstate__ |
Sérialisation d'objets(Cornichon)je fais |
__setstate__ |
Restaurer à partir d'objets sérialisés |
__str__ |
Méthode de stringification d'une classe(Soi-disant toString) |
__repr__ |
Méthode de sortie de la notation d'instance(Notation de type et de certains membres) |
__Str__
est similaire à __repr__
, mais __str__
permet aux humains de connaître le contenu de la variable (lisible), et __repr__
sert à vérifier si la variable est du type prévu ( Sans ambiguïté) (Référence). C'est une bonne utilisation d'inclure la forme dans __repr__
dans une variable de matrice, etc., et vous pouvez vérifier si la variable prévue est reçue et traitée. Il est intentionnel de formater l'état de l'instance avec «str» afin qu'elle puisse être lue par des humains lorsqu'elle est sortie vers la console de journalisation.
Il y a de nombreux cas où vous voulez accéder avec l'attribut ʻobj.xxxau lieu de la chaîne de caractères telle que ʻobj ["xxx"]
, mais dans ce cas, le ci-dessus __getattr__
etc. est valide. Ci-dessous, Exemple d'implémentation dans soundcloud-python (obj transmis dans __init__
depuis l'API Web Obtenu un objet de type dictionnaire).
class Resource(object):
"""Object wrapper for resources.
Provides an object interface to resources returned by the Soundcloud API.
"""
def __init__(self, obj):
self.obj = obj
def __getstate__(self):
return self.obj.items()
def __setstate__(self, items):
if not hasattr(self, 'obj'):
self.obj = {}
for key, val in items:
self.obj[key] = val
def __getattr__(self, name):
if name in self.obj:
return self.obj.get(name)
raise AttributeError
def fields(self):
return self.obj
def keys(self):
return self.obj.keys()
C'est une technique qui peut être utilisée lorsque vous souhaitez modifier dynamiquement des attributs en fonction de la réponse de l'autre partie, comme un wrapper pour WebAPI. Pour plus de détails sur son utilisation, voir [ici](https://www.inkling.com/read/learning-python-mark-lutz-4th/chapter-37/-getattr --- et --- get attribute-) détaillé.
Les attributs tels que les définitions d'instance / classe peuvent être extraits avec le module ʻinspect`.
>>> import inspect
>>> inspect.getmembers(some_instance)
Installation standard de Python 3.4.1, mais il n'y a pas d'énumération jusque-là.
Si vous voulez l'utiliser, installez et utilisez enum avec pip install enum34
.
import enum
class Color(enum.Enum):
Red = 10
Blue = 20
Yellow = 30
>>> Color.Red == Color.Red
True
>>> Color.Red == 10
False
#Ceci est faux car Enum est simplement un objet de type Enum. Il y a aussi un IntEnum qui rend ce True
>>> Color.Red == Color(10)
True
#Vous pouvez créer l'énumération correspondante en passant une valeur au constructeur
>>> Color.Red == Color["Red"]
True
#Lors de la création à partir du nom[]Spécifiez le nom avec
>>> {Color.Red:"red", Color.Blue:"blue"}
{<Color.Blue: 20>: 'blue', <Color.Red: 10>: 'red'}
#Peut également être utilisé comme clé de liste
Si vous souhaitez définir la chaîne de caractères de chaque élément, vous pouvez l'utiliser avec __str__
. Ceci est utile lorsque vous ne souhaitez pas disperser la définition lors de l'affichage des étiquettes.
class Color(enum.Enum):
Red = 10
Blue = 20
Yellow = 30
def __str__(self):
if self.value == Color.Red.value:
return "rouge"
elif self.value == Color.Blue.value:
return "Bleu"
elif self.value == Color.Yellow.value:
return "Bleu"
>>> print(Color.Red)
rouge
Il n'y en a pas, mais il est d'usage d'ajouter «» ou «_» au début des privés. Il n'y a pas de concept équivalent au soi-disant Protégé, comme vouloir le montrer uniquement aux classes héritées. Alors, quelle est la différence entre «» et «_»? Le degré auquel cela est caché de l'extérieur change.
class Test(object):
def __init__(self):
self.__a = 'a' # two underscores
self._b = 'b' # one underscore
>>> t = Test()
>>> t._b
'b'
>>> t.__a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'
t.__a isn't found because it no longer exists due to namemangling
>>> t._Test__a
'a'
Comme mentionné ci-dessus, si vous avez un trait de soulignement, vous pouvez y accéder comme d'habitude (il vous avertira si vous le vérifiez avec PEP), mais si vous avez deux traits de soulignement, vous ne pouvez pas y accéder à moins de faire _Test__a
. Cela en fait une forme privée (généralement invisible).
Référence
The meaning of a single- and a double-underscore before an object name in Python
Difference between _, __ and xx in Python
Vous ne pouvez pas définir de constantes en Python. Cependant, comme les tuples décrits plus tard sont des listes immuables, il est possible de créer des pseudo constantes en utilisant ceci (je pense que const est bien s'il y a une liste immuable ... ).
Ici, dans PEP8, les constantes doivent être connectées avec toutes les majuscules et les traits de soulignement, mais il n'y a pas de contrôle pour cela.
class Test(object):
def __init__():
pass
def get_num(self):
return 1
def add_num(self, num):
return self.get_num() + num
@classmethod
def test_print(cls):
print "test"
Le get_num
ci-dessus semble apparemment prendre un argument, mais c'est essentiellement une méthode sans argument.
Ensuite, les fonctions membres de la même classe sont appelées en utilisant ce premier argument implicite self
et cls
afin qu'elles soientself.get_num ()
.
En Python, il existe un objet appelé Taple, qui est à peu près une "liste immuable". Ceux-ci ont différentes méthodes de déclaration.
v_list = [10, 20, 30] # list
v_tuple = (10, 20, 30) # tuple
v_list[1] = 11 # ok
v_tuple[1] = 11 # error! 'tuple' object does not support item assignment
Taple peut également être la clé du dictionnaire en raison de ses caractéristiques. Les listes et taples sont également profondément impliqués dans les fonctions / méthodes qui gèrent des arguments de longueur variable.
def out_with_tuple(a,b,*args):
# a,Les arguments après b sont combinés en tuple
print(a,b,args)
>>> out_with_tuple(1,2,3,4,5)
(1, 2, (3, 4, 5))
def out_with_dict(a,b,**args):
print(a,b,args)
>>> out_with_dict(1,2,one=3,two=4,three=5)
(1, 2, {'three': 5, 'two': 4, 'one': 3})
Il est facile de considérer «» comme un pointeur, mais il représente un nombre arbitraire d'arguments et peut être regroupé en un taple pour «» et un dictionnaire pour «**» (peut être utilisé ensemble).
Ensuite, si l'appelant utilise «*», «**», la valeur list / taple peut être développée et passée en argument.
>>> def out(a,b):
... print(a,b)
>>> out([1,2]) #Si vous passez la liste normalement, naturellement NG
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: out() takes exactly 2 arguments (1 given)
>>> out(*[1,2])
(1,2) # *Développe les éléments de la liste et les sort(1,2)Sera la même chose que d'appeler
>>> out_with_dict(**{"a":1,"b":2})
(1, 2, {}) #Similaire à ce qui précède**Développe les arguments passés dans le dictionnaire
La valeur donnée comme argument par défaut pour une méthode ou une fonction doit être immuable. C'est généralement le cas, donc il n'y a pas de problème, mais sachez que les tableaux vides sont mutables.
>>> class ArrayDefault():
>>> def __init__(self, array=[]):
>>> self.array = array #! mutable default value
>>> a = ArrayDefault()
>>> len(a.array)
0
>>> a.array += [1,2,3]
>>> a.array
[1,2,3]
>>> b = ArrayDefault()
>>> b.array
[1, 2, 3] # !!!!!
Pour une raison quelconque, la valeur est pré-remplie dans l'instance de «b» qui n'a rien à voir avec «a». Cela semble complètement compliqué et bizarre, c'est pourquoi l'argument doit être immuable. La portée de l'argument par défaut semble être la même que celle de cette méthode / fonction, et si elle n'est pas immuable, elle se comporte comme une variable globale et se comporte comme décrit ci-dessus.
Par conséquent, dans le cas ci-dessus, il est nécessaire de passer à un processus tel que définir Aucun comme argument par défaut et définir [] si Aucun. Comme avec les tableaux, des précautions doivent être prises dans les cas où la référence est définie comme valeur initiale.
Default Parameter Values in Python
Les surcharges avec des arguments différents et définies avec le même nom ne peuvent pas être utilisées en Python. Par conséquent, si vous souhaitez utiliser la surcharge, vous devez utiliser l'argument par défaut ou déterminer le type de l'argument en interne pour le gérer en créant des branches dans une seule méthode. De plus, les méthodes de classe et les méthodes membres portant le même nom ne sont pas autorisées.
Cependant, en utilisant singledispatch, le branchement conditionnel peut être éliminé et une implémentation surchargée peut être réalisée (standard de Python 3.4). Alimenté par).
En Python, il est possible d'implémenter des calculs par des opérateurs tels que «+» et «-» (soi-disant surcharge d'opérateurs) (Reference) ).
class Point(object):
def __init__(self, x, y):
self.x = 0 if x is None else x
self.y = 0 if y is None else y
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Point(x, y)
def __str__(self):
return "x:{0}, y:{1}".format(self.x, self.y)
>>> print(Point(1, 2))
x:1, y:2
>>> print(Point(1, 2) + Point(1, 2))
x:2, y:4
Il est également possible d'implémenter des opérateurs logiques tels que «==» et «>». Cependant, il est assez difficile de définir tous les opérateurs sans aucune lacune. S'il s'agit d'un système de calcul numérique, il est préférable de vérifier s'il existe une bibliothèque appropriée plutôt que de l'implémenter par vous-même.
À partir de Python3 (notamment à partir de Python3.5), il est possible d'écrire des types pour les valeurs de retour des arguments et des fonctions.
def greeting(name: str) -> str:
return 'Hello ' + name
À partir de Python 3.6, vous pouvez également ajouter des informations de type aux variables (PEP 526).
my_string: str
my_dict: Dict[str, int] = {}
Ceci est appelé annotation de type, et bien que cela ne donne pas d'erreur à l'exécution, il peut être vérifié à l'avance en utilisant ces informations. Les outils de vérification incluent mypy, qui peut être utilisé pour vérifier l'intégrité du type avant l'exécution. Voir ci-dessous pour plus de détails.
Monde typé commençant par Python
De plus, il y en a qui ont @
qui ressemble à l'annotation Java, mais ce n'est pas une annotation mais un "décorateur", et son comportement est complètement différent, ce qui affecte l'exécution de la fonction.
Comme son nom l'indique, «décorer» fonctionne comme une «fonction qui encapsule une fonction».
import functools
def makebold(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return "<b>" + func(*args, **kwargs) + "</b>"
return wrapper
def makeitalic(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return "<i>" + func(*args, **kwargs) + "</i>"
return wrapper
@makebold
@makeitalic
def hello(your_name):
return "hello {0}.".format(your_name)
>>> print hello("hoge") ## returns <b><i>hello hoge.</i></b>
Référence: Comment puis-je créer une chaîne de décorateurs de fonctions en Python?
Ce qui précède est identique à l'exécution de makebold (makeitalic (hello)) (your_name)
(exécuté séquentiellement à partir du décorateur le plus proche de la définition de la fonction).
Si vous souhaitez vérifier avant d'exécuter la méthode (autorisation, etc. Vérifier les remplacements, Etc.), ou lorsque vous souhaitez insérer un traitement avant et après l'exécution (mesure du temps d'exécution, etc.). De plus, functools.wrap
évite que les informations de la fonction ne soient remplacées par la fonction décorée au lieu de la fonction d'origine en décorant (here. 20090427/1240838573)).
Il est assez difficile d'obtenir les décorateurs donnés à une méthode Par conséquent, à des fins de méta-programmation (comme obtenir une méthode annotée et l'exécuter), il est préférable de la mettre à niveau vers Python3 et d'utiliser l'annotation.
En Python, l'espace de noms est coupé (automatiquement) pour chaque fichier sans déclarer d'espace de noms ou de package. Le nom de l'espace de noms coupé pour chaque fichier est synonyme du nom du fichier, donc lorsque vous appelez TestClass
défini dans package / test_class.py
, il est nécessaire d'utiliser from package.test_class import TestClass
. Il y a.
De plus, comme il est coupé en unités de fichiers, une déclaration d'importation est requise lors du référencement de fichiers dans le même dossier. Notez que le dossier est reconnu comme un package s'il existe un fichier appelé __init __. Py
(il ne doit pas nécessairement provenir de Python3).
Comme avec Java, si vous souhaitez importer par nom de package / classe (comme from package import TestClass
), vous pouvez le gérer en écrivant l'instruction d'importation du fichier dans __init __. Py
. C'est parce que la partie from package
est chargée avec __init __. Py
dans le dossier, donc s'il y a une instruction d'importation ici, ce sera la même chose que l'importation du fichier.
Notez que lors de l'importation de fichiers référencés mutuellement (A fait référence à B et B fait référence à A), cela devient un blocage et ne peut pas être importé. Pour éviter cela, il est nécessaire de prendre certaines mesures telles que l'importation dans le cadre du traitement nécessaire plutôt qu'au début du fichier (Référence. python)).
ʻSi name == "main": peut décrire ce qui se passe quand il est exécuté comme un script (lorsqu'il est exécuté avec
python xxx.py`) (voir [Environnement de script de premier niveau](http: // docs). .python.jp / 2 / bibliothèque / __ main __. html)).
if __name__ == "__main__":
print "Run Script"
Peu importe que ce soit le fichier qui définit la classe ou le fichier qui définit la fonction.
Par conséquent, si vous voulez vérifier le fonctionnement de la classe que vous définissez pendant un moment, mettez l'instruction if ci-dessus au bas du fichier et écrivez le processus de vérification de l'opération sous python xxx.py Vous pouvez le vérifier en définissant
. C'est très pratique.
En Python, il est possible d'effectuer des opérations dans un tableau comme suit.
>>> [ x for x in [1, 2, 3, 4, 5] if x > 3]
[4, 5]
>>> [ x*2 for x in [1, 2, 3, 4, 5]]
[2, 4, 6, 8, 10]
#Il est également possible d'utiliser des fonctions
>>>def calc_double(x):
>>> return x*2
>>> [ calc_double(x) for x in [1, 2, 3, 4, 5]]
[2, 4, 6, 8, 10]
Cela fonctionne de la même manière que les fonctions intégrées telles que map
et filter
, mais dans certains cas, il est plus facile d'écrire avec une meilleure lisibilité. Depuis Python3, map
et filter
ne renvoient pas la liste elle-même, mais il renvoie un itérateur. -list-in-python-3-x), donc si vous voulez le gérer avec une liste comme Python2, utilisez la notation d'inclusion de liste, si vous voulez enchaîner de l'itérateur au traitement suivant, utilisez map
/ filter
etc. Il est facile de prendre en charge les deux versions si vous les conservez.
De plus, Il semble que la vitesse d'exécution est rapide.
Depuis Python3.6, il est possible de gérer des itérateurs asynchrones même avec cette notation d'inclusion de liste (PEP 530). ..
result = [i async for i in async_iter() if i % 2]
result = [await fun() for fun in async_funcs if await condition()]
En Python, vous pouvez créer des fonctions anonymes en utilisant lambda
.
>>> list(map(lambda x: x * 2, range(5)))
[0, 2, 4, 6, 8]
Dans ce qui précède, «map» est utilisé et la fonction «lambda x: x * 2» est appliquée à chaque valeur de «range (5)».
La fonction créée par lambda
peut également être affectée à une variable, et ce qui précède est équivalent à ce qui suit.
>>> f = lambda x: x * 2
>>> list(map(f, range(5)))
[0, 2, 4, 6, 8]
Combiné avec la notation d'inclusion de liste ci-dessus, le traitement suivant est également appliqué.
>>> f = lambda a, b: a + b
>>> [f(*z) for z in zip([1, 2, 3], [4, 5, 6])]
[5, 7, 9]
zip
est une fonction pratique qui prend plusieurs tableaux comme arguments et les rassemble pour chaque index, et zip ([1, 2, 3], [4, 5, 6]) ʻis
[(1, 4), ( 2, 5), (3, 6)] ». Ceci est étendu à l'argument de la fonction f
using` * ʻet traité.
Les instructions Python for sont identiques à chacune et ne peuvent pas être indexées par défaut. Si vous souhaitez utiliser index dans une instruction de boucle, procédez comme suit.
for index, value in enumerate(list):
print "index:" + index
Si vous voulez juste tourner par index, vous pouvez également écrire comme suit (Comme il n'y a pas de list.length
en Python, utilisez len (list)
pour obtenir la longueur).
for index in range(len(list)):
print "index:" + index
Comme propriété pratique, vous pouvez définir else dans l'instruction Python for (bien que while puisse être utilisé plus souvent).
child = "Bob"
for c in ["Alice", "Tom", "Ann", "Cony"]:
if c == child:
break
else:
print("{} is not here.".format(child))
Le processus défini par ʻelse est traité lorsque
break` n'est pas exécuté. Par conséquent, il peut être utilisé pour décrire le traitement lorsque la détection ne peut pas être effectuée dans la boucle.
Puisque Python n'a pas d'instruction switch, if-else est utilisé à la place. Eh bien, vous pourriez penser, mais Python a une indentation et si est assez propre, donc ce n'est pas trop un problème.
Aussi, pour cette raison, vous pouvez penser que vous ne pouvez pas écrire une instruction if sur une ligne (soi-disant opérateur ternaire) en Python, mais en Python 2.5 ou supérieur, vous pouvez écrire comme suit ([PEP 308-] - Expressions conditionnelles](voir http://legacy.python.org/dev/peps/pep-0308/).
>>> test = 1
>>> "test eq 1" if test == 1 else "test not eq 1"
'test eq 1'
A partir de Python3.5, le traitement asynchrone peut être facilement implémenté en utilisant la syntaxe ʻasync / ʻawait
(bien qu'il était possible d'implémenter avec ʻasyncio` avant cela, en tant que grammaire Mis en œuvre).
Lors du traitement d'un certain processus continu («tâches» dans ce qui suit) dans plusieurs processus, il peut être écrit comme suit.
import asyncio
import random
tasks = asyncio.Queue()
for t in range(10):
tasks.put_nowait(t)
async def execute(p):
while not tasks.empty():
t = await tasks.get()
await asyncio.sleep(random.randint(0, 3)) # emulate the waiting time until task t finish
print("Process{} done task {}".format(p, t))
return True
if __name__ == "__main__":
loop = asyncio.get_event_loop()
execution = asyncio.wait([execute(process_no) for process_no in range(2)])
loop.run_until_complete(execution)
Le résultat de l'exécution est le suivant (* Bien sûr, le résultat sera différent à chaque exécution).
Process1 done task 0
Process0 done task 1
Process1 done task 2
Process0 done task 3
Process1 done task 4
Process0 done task 5
Process1 done task 6
Process0 done task 7
Process0 done task 9
Process1 done task 8
Veuillez vous référer à l'article suivant pour plus de détails.
Traitement asynchrone en Python: référence inverse asyncio
Il est maintenant possible de créer des itérateurs asynchrones plus facilement en utilisant yield
de Python 3.6 ([PEP 525](https://docs.python.org/3.6/whatsnew/3.6.html#" whatsnew36-pep525)).
async def ticker(delay, to):
"""Yield numbers from 0 to *to* every *delay* seconds."""
for i in range(to):
yield i
await asyncio.sleep(delay)
En Python, il existe un site appelé PyPI qui héberge des packages, et en publiant le package créé ici, il peut être largement utilisé par d'autres personnes avec pip install etc. Vous pouvez l'obtenir (comme Maven en Java, rubygems.org en Ruby, nuget en .NET).
En ce qui concerne cette méthode, si vous recherchez normalement, l'ancienne méthode sera souvent interceptée, veuillez donc vous référer à ce qui suit pour la dernière méthode de téléchargement.
Publier la bibliothèque créée en Python sur PyPI
Voir également ci-dessous pour tout autre chose que ceux répertoriés ici. [python] 10 vrais pièges de Python qui sont trop détaillés pour être véhiculés
Recommended Posts