Ich bin mit Python auf verschiedene Punkte gestoßen, aber hier sind einige Tipps, die ich hätte kennen müssen, bevor ich mit dem Schreiben angefangen habe, damit ich solche Fallen vermeiden und ein angenehmes Python-Leben führen kann.
Es gibt 2 Serien und 3 Serien in Python, und 3 Serien haben Änderungen, die sich auf die Abwärtskompatibilität auswirken. Das heißt, Python3-Code funktioniert möglicherweise nicht in Python2 (und umgekehrt).
Python3 hat verschiedene Punkte in Python2 verbessert, und wenn Sie es von nun an verwenden, wird es im Grunde mit der neuesten Version von Python3 durchgeführt (auch unten habe ich angegeben, was mit Python3 verbessert werden soll). Das Beste von allem ist, dass Python2 [Ende der Unterstützung ab dem 1. Januar 2020] ist (http://legacy.python.org/dev/peps/pep-0373/). Es gibt also keinen Grund mehr, Python 2 von nun an zu verwenden. Diejenigen, die noch Python 2 verwenden, werden von Grundschülern entlassen.
Es gibt jedoch einige Pakete, die noch nicht mit Python3 kompatibel sind, und ob Sie ein solches Paket in Ihrem Projekt erreichen können oder nicht, ist ein Wendepunkt in Ihrem Schicksal. Sie können den Support-Status in einer Liste unter hier überprüfen. Ich denke jedoch, dass die meisten Pakete bereits unterstützt werden oder auf Python3 ausgeführt werden sollten Es gibt auch eine automatische Konvertierung von 2 nach 3. html). Im Gegenteil, wenn Python3 nicht unterstützt wird, kann gesagt werden, dass der Wartungsstatus angezweifelt werden sollte. Google App Engine ist auch endlich kompatibel mit Python 3 in der zweiten Generation. Selbst OpenAI, ein führendes Forschungsinstitut für künstliche Intelligenz, hat auf Python 3 umgestellt, sodass diejenigen, die sagen, "maschinelles Lernen ist noch nicht ...", nicht zumindest fortgeschritten sind. Als Mensch müssen Sie sich nicht auf das verlassen, was Sie sagen.
Bei der Entwicklung von Python ist es fast unerlässlich, pip und virtualenv zusätzlich zu Python selbst zu installieren. Hier finden Sie eine Zusammenfassung der Einrichtung von Python, pip und virtualenv in jeder Umgebung.
Ich denke, es gibt viele Gründe, warum ich maschinelles Lernen als Grund für Python wählen möchte, deshalb werde ich zuerst die Methode dafür vorstellen. Um eine Umgebung für maschinelles Lernen zu erstellen, empfehlen wir die Verwendung von Miniconda, unabhängig davon, ob es sich um Mac / Linux / Windows handelt.
Die Installationsmethode ist wie auf der obigen Seite gezeigt. Miniconda verfügt über eine Funktion zum Erstellen einer Umgebung (virtuelle Umgebung) für jede Anwendung, und es ist einfach, Pakete für maschinelles Lernen zu installieren. Außerdem kann cuda installiert werden, das für die GPU erforderlich ist, und mingw, eine Windows-Build-Umgebung. Es ist möglich und es ist einfach, andere Tools als einfache Pakete einzuführen. Bei TensorFlow werden die Tools rund um die GPU durch Installation mit conda installiert, und die CPU-Version arbeitet mit hoher Geschwindigkeit (Details). Tensorflow-in-Anaconda /)).
Mit dem folgenden Befehl können Sie nach der Installation von Miniconda eine allgemeine Umgebung für maschinelles Lernen wie scikit-learn auf Jupyter Notebook erstellen.
conda create -n ml_env numpy scipy scikit-learn matplotlib jupyter
activate ml_env
Ich habe eine Umgebung namens "ml_env" mit "conda create" erstellt und mit "enable" aktiviert. Einzelheiten zur Verwendung des Befehls "conda" finden Sie unter hier (für Windows / Powershell wird er nicht gestartet. Weitere Informationen finden Sie unter [Windows-Abschnitt] ](Https://qiita.com/icoxfog417/items/e8f97a6acad07903b5b0#windows%E3%81%AE%E5%A0%B4%E5%90%88) Referenz).
Die Umgebung von Miniconda wird auch in "Dockerfile" bereitgestellt, und Sie können einfach einen Container erstellen, indem Sie ihn mit "FROM continuumio / miniconda3" usw. erben.
Wenn Sie eine maschinelle Lernumgebung für einen Docker-Container freigeben möchten oder eine Bereitstellung in einer PaaS-Umgebung wie Heroku planen, empfehlen wir die Verwendung von Docker ([Heroku unterstützt Docker-Push mit Containerregistrierungsfunktion. [Https://devcenter.heroku.com/articles/container-registry-and-runtime].
Anaconda wird aus den folgenden zwei Gründen nicht als maschinelle Lernumgebung empfohlen.
Beachten Sie, dass Sie auch mit Miniconda, wenn Sie nicht verwendete Pakete nicht regelmäßig mit "conda clean --all" löschen, ein paar G leicht nehmen können **. Dies liegt daran, dass conda Pakete, die einmal heruntergeladen wurden, als Cache speichert. Selbst wenn Sie ein altes Paket verwenden, das Sie jetzt nicht verwenden, bleibt es so lange bestehen, wie Sie es nicht löschen. Es ist also gut, es zu löschen.
Python ist standardmäßig enthalten, entspricht jedoch möglicherweise nicht der Version, die Sie entwickeln möchten. Daher ist es gut, pyenv zu verwenden, um die für jedes Projekt verwendete Python-Version zu wechseln. Wie oben erwähnt, können Sie bei Verwendung von Miniconda die Version von Python hier verwalten, sodass Sie pyenv nicht installieren müssen. Wenn Sie die virtuelle Umgebung aktivieren ("aktivieren"), tritt ein Befehls-Batting auf und die Shell hängt. Daher ist es besser, pyenv nicht zu installieren, wenn Sie Miniconda verwenden.
pyenv install x.x.x
. Stellen Sie dann den Python so ein, dass er mit pyenv global x.x.x
verwendet wirdPython, das in jedem Projekt verwendet wird, ist in pyenv local x.x.x
festgelegt.
Nach der Installation einer neuen Python-Umgebung mit pyenv ist pyenv rehash
erforderlich. Wenn Sie die Installation immer noch nicht finden können, starten Sie das Terminal neu.
Sie können es normal installieren, wir empfehlen jedoch Miniconda.
Bitte beachten Sie, dass ab 2018 enable
noch nicht in PowerShell gestartet wird. Wenn Sie nicht jedes Mal zu "cmd" wechseln möchten, können Sie es verwenden, indem Sie "pscondaenvs" installieren (das Folgende gilt für die Installation in der globalen Umgebung ("root")).
conda install -n root -c pscondaenvs pscondaenvs
Die Paketverwaltung wird eingeführt, um Bibliotheken zu installieren, und die virtuelle Umgebung wird eingeführt, um die Python-Version und die Bibliotheken zu isolieren, die für jedes Projekt verwendet werden sollen.
Da pip
standardmäßig ab Python 3.4 installiert ist, muss es derzeit nicht separat installiert werden. Wenn Sie altes Python verwenden, installieren Sie es mit get_pip.py.
virtualenv
kann mit pip install virtualenv
installiert werden.
Offiziell wird jedoch empfohlen, Pipenv zu verwenden, das die Funktion pip / virtualenv enthält. Mit Pipenv ist es wie mit npm in Node.js einfach, abhängige Bibliotheken gleichzeitig mit der Installation zu schreiben und Entwicklungs- / Produktionsinstallationsbibliotheken zu trennen.
Die Python-Entwicklung erfolgt im Allgemeinen mit dem folgenden Setup.
Wenn es als Befehl umgeschrieben wird, hat es die folgende Form. Wir werden drei Fälle vorstellen, wenn Sie das neue pipenv verwenden, wenn Sie das herkömmliche pip / virtualenv verwenden und wenn Sie conda verwenden.
In pipenv
muss die Erstellung einer virtuellen Umgebung nicht explizit angewiesen werden. Wenn Sie mit "pipenv install" installieren, wird eine virtuelle Umgebung erstellt und dort installiert. Es wird jedoch in einem Pfad erstellt, der standardmäßig nicht gut verstanden wird, und es ist schwierig, die Vorteile der Codespeicherung in einer integrierten Entwicklungsumgebung so wie sie ist zu erhalten.
Daher ist es besser, vor der Verwendung "PIPENV_VENV_IN_PROJECT = 1" (oder "true") zu setzen. Auf diese Weise wird eine virtuelle Umgebung in ".venv" des aktuellen Ordners erstellt.
# 1.Erstellen Sie einen Projektordner
mkdir myproject
cd myproject
# 2.Installieren Sie die erforderlichen Bibliotheken mit pipenv
pipenv install xxxx
##Bibliothek nur für die Entwicklung verwendet(Für Tests usw. verwendete Bibliotheken usw.)Zu`-dev`Anziehen
pipenv install --dev xxxx
##Die von pipenv installierte Bibliothek ist automatisch Pipfile.Geschrieben zum Sperren. Wenn Sie es laden und installieren möchten, führen Sie einfach pipenv install aus
pipenv install
# 3.Lauf
pipenv run python xxx.py
##Wenn Sie die Shell starten möchten, verwenden Sie die pipenv-Shell
pipenv shell
#Wenn Sie die erstellte Umgebung löschen,
pipenv --rm
# 1.Erstellen Sie einen Projektordner
mkdir myproject
cd myproject
# 2.Erstellen einer virtuellen Umgebung venv ist ein Ordnername und die Umgebung für das Projekt wird hier vorbereitet
virtualenv venv
# 3.Aktivieren Sie die virtuelle Umgebung und installieren Sie die erforderlichen Module mit pip
#Für Windows venv/Scripts/activate.bat Wenn Sie die Shell von Git verwenden, können Sie dies auch mit der Quelle auf die gleiche Weise tun
#Beachten Sie, dass die virtuelle Umgebung global installiert wird, wenn Sie sie nicht aktivieren. Deaktivieren Sie sie daher.
source venv/bin/activate
pip install xxxx
#Liste erstellt durch Pip Freeze(requirements.txt)Bei der Installation von
pip install -r requirements.txt
# 4.Lauf
python xxx.py
# 1.Erstellen Sie eine virtuelle Umgebung(so etwas wie virtualenv)
conda create -n my_env numpy scipy
##Zeigen Sie eine Liste der virtuellen Umgebungen an
conda info -e
# 2.Virtuelle Umgebung aktivieren
activate my_env # Windows
source activate my_env # Max/Linux
##Zusätzliche Installation in einer virtuellen Umgebung(Bei Angabe der Version conda install scipy=0.12.0 usw.)
conda install scikit-learn
##Installieren Sie mit pip für Dinge, die mit conda nicht erhalten werden können(Unterstützung durch Einfügen von pip in die virtuelle Umgebung)
conda install pip
pip install Flask
##Update der installierten Pakete(conda selbst ist conda update conda)
conda update numpy
# 3.Exportieren Sie die mit conda erstellte Umgebung/Lesen
conda env export > environment.yml
conda env create -f environment.yml
# 4.Deaktivieren Sie die virtuelle Umgebung
deactivate # Windows
source deactivate # Max/Linux
Siehe hier für Details.
Die oben genannten Ordner für virtuelle Umgebungen (venv usw.) und .pyc
-Dateien sollten für die Versionsverwaltung ausgeschlossen werden.
Die .pyc-Datei ist eine Datei zur Beschleunigung der Ausführung. Nach der Ausführung wird für jede Datei eine Datei erstellt. Wenn Sie dies in die Versionsverwaltung einfügen, wird die Datei verdoppelt, sodass Sie sie entfernen müssen (Sie können auch die Option -B hinzufügen oder die Umgebungsvariable PYTHONDONTWRITEBYTECODE festlegen, um zu verhindern, dass sie generiert wird. Can (Referenz)).
Weitere Dateien, die ignoriert werden sollten, finden Sie unter Python .gitignore.
Tips
Darüber hinaus gibt es je nach Bibliothek einige, die mit "pip install" nicht gehorsam eingegeben werden können. Dies macht sich in Windows bemerkbar. In vielen Fällen kann dies durch "conda install" vermieden werden. Wenn das Problem jedoch weiterhin besteht, führen Sie die folgenden Maßnahmen aus.
pip install <Dateipfad>
(beiseite) Durch die Verwendung von Wheel können die abhängigen Bibliotheken jedoch in einem kompilierten Zustand in das Repository aufgenommen werden. Dies verhindert, dass die Pip-Installation beim Verteilen und Bereitstellen nicht in der Umgebung der anderen Partei durchgeführt werden kann. Weitere Informationen Dokumentreferenz).Nachdem die Python-Entwicklungsumgebung eingerichtet ist, sollten Sie bei der Entwicklung mit Python, dem Hauptthema, einige Punkte beachten.
Bitte beachten Sie, dass japanische Zeichen verstümmelt werden, wenn Sie am Anfang jeder Datei nicht Folgendes hinzufügen. Wie in hier erwähnt, ist es eine gute Idee, es immer am Anfang der Datei zu platzieren.
# -*- coding: utf-8 -*-
In Python3 ist die Standardcodierung UTF-8, daher ist diese Unterstützung nicht erforderlich (PEP 3120 - Verwenden von UTF-8 als Standardquellcodierung. / dev / peps / pep-3120 /)).
Wie unten erwähnt, sollten Sie, wenn davon ausgegangen wird, dass beide Python 2/3 unterstützt werden, und wenn Sie die Vorteile von Python 3 (insbesondere Unicode-Vereinheitlichung) erhalten möchten, auch Folgendes importieren ([hier](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) Referenz).
from __future__ import division, print_function, absolute_import, unicode_literals
Python hat eine offiziell definierte Codierungsanleitung (PEP8) (Original/ [japanische Übersetzung](http: //) pep8-ja.readthedocs.io/ja/latest/)), viele integrierte Entwicklungsumgebungen ermöglichen die Überprüfung damit.
Dies ist praktisch, da Sie die Punkte wie zu viele Zeilenumbrüche und das Vorhandensein von Leerzeichen im Detail überprüfen und die übersehenen Punkte korrigieren können. Im Gegenteil, wenn Sie es nicht von Anfang an einsetzen, wird es schwierig sein, es später zu beheben. Lassen Sie es uns also beim Einrichten der Umgebung einsetzen.
Wie der Name schon sagt, ist das Paket pep8, das die PEP8-Konformität überprüft, derzeit nicht gepflegt [pycodestyle](https: //). Bitte beachten Sie, dass es sich um github.com/PyCQA/pycodestyle handelt. (Der Hintergrund ist, dass es verwirrend ist, ob der Paketname "pep8" eine Konvention oder ein Tool ist, also Umbenannt Weil es vorgeschlagen wurde).
Wenn Sie nur logische Überprüfungen (unnötige Importe, nicht verwendete Variablen usw.) zusammen mit pep8 beibehalten möchten, werden pycodestyle, das pep8 überprüft, und pyflakes, die logische Überprüfungen durchführen, gepackt [flake8](http: //: flake8.pycqa.org/en/latest/) wird empfohlen. Pylint kann auf verschiedene Arten überprüft werden, aber es gibt viele Szenen, die ärgerlich sein können, und Sie müssen einen bestimmten Betrag bezahlen, um sie auf ein angemessenes Niveau einzustellen.
Daher möchte ich zuerst den Pfad von flake8 empfehlen und dann zu Pylint wechseln, wenn es notwendig ist, den Codierungsstandard zu verbessern.
Da "unittest" in Python [als Standard installiert] ist (http://docs.python.jp/2/library/unittest.html), muss kein Paket für Unit-Tests hinzugefügt werden.
unittest2
sieht aus wie ein neues Framework, ist aber grundsätzlich nicht erforderlich, um es einzuführen, da es für die Verwendung des Unit-Test-Frameworks für die neue Version in der alten Version vorgesehen ist (nebenbei habe ich diese Nummer angegeben). Ich möchte, dass Sie den Paketnamen nicht mehr verwenden (z. B. urllib2).
In Python werden die normale Zeichenfolge "str" und die Unicode-Zeichenfolge "unicode" getrennt.
str = "abc" # An ordinary string
uni_str = u"abc" # A Unicode string
Intern gibt es nicht viel Probleme mit str, wie es ist, aber wenn externe Eingaben / externe Ausgaben wie Webanwendungen beteiligt sind, ist es besser, mit Unicode zu vereinheitlichen (wenn Sie ein Framework verwenden, welches Sie müssen wissen, ob es eingeht oder ob Sie den Wert übergeben sollten. In Python3 ist es zu Unicode vereinheitlicht. Außerdem können Sie in Python2 eine Vereinheitlichung zu "Unicode" vornehmen, indem Sie "aus future import unicode_literals" verwenden.
Im Python2-System wird das Ergebnis der Division zwischen Ganzzahlen wie 1/3 nicht zum Float-Typ.
>>> 1/3
0
>>> 3/2
1
Dies wird in Python3 gelöst (im obigen Beispiel wird es zu einem normalen Ergebnis einer arithmetischen Operation wie 0,333 ..., 1,5). Wenn Sie Python2 mit Python3 identisch machen möchten, können Sie es lösen, indem Sie zu Beginn den folgenden Import ausführen.
from __future__ import division
Zusätzlich gibt es in der Division ein Zeichen "//". Auf den ersten Blick scheint dies ein Operator für die Erstellung eines Quotienten zu sein, ist es aber nicht. Genau genommen ist die Operation mit "//" der "maximale ganzzahlige Wert, der das Berechnungsergebnis nicht überschreitet". Wenn beispielsweise 3 durch 2 geteilt wird, ist dies 1,5, und die maximale Ganzzahl, die diese nicht überschreitet, ist 1. Dies ist so gut wie ein Quotient, aber das Problem ist, wenn der Wert negativ ist.
>>> -3 / 2
-2
Das Ergebnis ändert sich nur, weil das Vorzeichen negativ wird. Was ist das? Sie könnten denken, aber wenn es negativ ist, ist die maximale Ganzzahl, die -1,5 nicht überschreitet, "-2", was eine Spezifikation ist, kein Fehler. Und diese Spezifikation ist in Python3 dieselbe.
Wenn Sie den Quotienten sicher berechnen möchten, ist es daher besser, ihn so zu berechnen, dass das Ergebnis nach dem Dezimalpunkt schwebt und abgeschnitten wird. Bei Python3 wird das mit /
berechnete Ergebnis einfach abgeschnitten.
Es gibt eine eingebaute Funktion namens "divmod", die den Quotienten und den Rest gleichzeitig berechnet. Seien Sie jedoch vorsichtig, da der "Quotient" in dieser Funktion mit dem Berechnungsergebnis von "//" identisch ist (solange im Dokument "Quotient" angegeben ist. Ich denke, das ist ein Fehler, aber ...).
Der in Python gerundete "Round" -Prozess ist eine Bankrundung (auch Rundung auf die nächste gerade Zahl, JIS-Rundung und ISO-Rundung genannt). Insbesondere wenn die Zahl nach dem Dezimalpunkt "0,5" ist, wird sie näher an eine gerade Zahl verschoben. Dies ist ein Prozess, der ausgeführt wird, da, wenn 0,5 immer auf einen positiven Wert aufgerundet wird, der Wert der Summe nach dem Runden (aufgerundet) in der Summe vor und nach dem Runden größer ist = es eine Verzerrung gibt ( Weitere Informationen finden Sie in der Bruchverarbeitung von Wikipedia (https://ja.wikipedia.org/wiki/%E7%AB%AF%E6%95%B0%E5%87%A6%E7%90%86).
>>> round(3 / 2)
2
>>> round(1 / 2)
0
Da "1/2 = 0,5", denke ich, ist es 1, aber dies ist eine Geschichte der arithmetischen Rundung, und im Fall der Bankrundung, wie oben erwähnt, wird sie auf "sogar am nächsten an 0,5" gerundet, dh auf 0. Beachten Sie, dass ** Python2 eine gerundete Arithmetik ist, seien Sie also vorsichtig **.
Außer Python gibt es Sprachen wie C #, die Bankrundungen verwenden (siehe [hier] für Details [https://qiita.com/nekonenene/items/05b85048feb05a6bb9ee#%E4%B8%80%E8%A6%]). Siehe A7% E8% A1% A8)).
In der folgenden gut eingeführten Klassendeklaration handelt es sich um eine Klasse alten Stils.
class MyClass():
pass
Was unterscheidet sich von der alten Stilklasse? Es gibt viele Dinge, aber zumindest das Erstellen mit der alten Stilklasse hat jetzt keinen Wert mehr. In der alten Stilklasse funktioniert das "Super", das die übergeordnete Klasse aufruft, nicht, daher weiß ich nicht, wofür die Vererbung gedacht ist.
Daher wird die Klasse wie folgt deklariert.
class MyClass(object):
pass
Es erbt "Objekt". In Python3 handelt es sich standardmäßig um eine neue Stilklasse alte Stilklasse wird gelöscht.
Python 3 vereinfacht auch den Aufruf der übergeordneten Klasse. In Python2 war es eine komplizierte Aufrufmethode wie "super (Name der untergeordneten Klasse, self) .parent_method ()", aber in Python3 kann sie normal mit "super (). Parent_method ()" aufgerufen werden.
Vererbung ist möglich, aber es gibt keinen Mechanismus, um die Implementierung auf niedrigere Klassen zu zwingen. Abc wurde jedoch standardmäßig aus Python 2.6 hinzugefügt, und es wurde möglich, eine pseudo-abstrakte Klasse zu implementieren (abc ist eine Abkürzung für abstrakte Basisklasse).
from abc import ABCMeta
class MyABC:
__metaclass__ = ABCMeta
def describe(self):
print("I'm abc")
@abstractmethod
def must_implements(self):
pass
In Python3 können Sie beim Erstellen einer Klasse die Metaklasse verwenden, um sie einfacher zu schreiben.
from abc import ABCMeta
class MyABC(metaclass=ABCMeta):
...
Sie können auch eine Klasse registrieren, die "register" unter Ihrer Kontrolle verwendet (Unterklasse). Da es jedoch einfach "so aussieht", ist Tupel selbst im folgenden Beispiel keine geerbte Klasse von MyABC, und die in MyABC tatsächlich implementierten Methoden können nicht verwendet werden.
MyABC.register(tuple)
assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)
().describe() # Attribute Error
Obwohl es in "isinstance" wahr ist, scheint es verwirrend zu sein, einen Attributfehler in der Methode zu erhalten, so dass ich mir die Verwendungsszene nicht sehr vorstellen kann. Ich denke, es ist besser, es normal zu erben. Natürlich löst eine Methode, die normalerweise eine Klasse deklariert und zur Implementierung gezwungen wird, eine Ausnahme in der übergeordneten Klasse aus.
Python wird eine der wenigen Sprachen sein, die Mehrfachvererbung unterstützen.
class MultiInheritance(Base1, Base2, Base3):
...
Die Lösung wird in der Reihenfolge von links ausgeführt. Wenn dies nicht der Fall ist, wird oben Base1 durchsucht, dann Base2 usw. Super ist die Klasse ganz links, wenn sie normal aufgerufen wird.
Wie oben erwähnt, hat Python keine Schnittstelle, daher verwenden Sie stattdessen die Mehrfachvererbung (oder Module / Mix-In). Ich denke, es ist besser, Mehrfachvererbung nicht für andere Zwecke zu verwenden. Da jedoch jeder wie eine Klasse aussieht, ist es besser, die Regel des Klassennamens zu bestimmen, z. B. mit "I" für die als Schnittstelle verwendete zu beginnen (oder eine Klasse wie "Schnittstelle / Modul" zu erstellen und zu erben).
In Python sind "new" und "init" beide Konstruktoren, nicht wahr? Es gibt zwei Funktionen, die aussehen.
Verwenden Sie grundsätzlich __init__
.
Wie Sie jedoch aus dem Argument "self" ersehen können, ist "__init __" ein "Initialisierungsprozess nach dem Erstellen der Instanz" und kein reiner Konstruktor. __new__
ist der Vorgang, bei dem die Instanz zur Initialisierung mit __init__
zurückgegeben wird. Wenn Sie dies tun möchten, können Sie eine andere Instanz als Ihre eigene Klasse zurückgeben, aber der Verdienst ist nicht so groß. Wird es für die Singleton-Implementierung verwendet?
Python-Instanzen haben versteckte Attribute, die von zwei Unterstrichen umgeben sind, wie z. B. "__init __" oben (auch in der Klassen- / Funktionsdefinition selbst). Diese werden zum Speichern von Metainformationen und zum Ausführen grundlegender Vorgänge verwendet (z. B. Verhalten beim Festlegen / Abrufen von Werten in Attributen). Details finden Sie in Datenmodell. Die häufig verwendeten / wahrscheinlich nützlichen sind jedoch die folgenden.
Attributname | Inhalt |
---|---|
__class__ |
Klassendefinition.__class__.__name__ Sie können den Klassennamen mit erhalten |
__dict__ |
Alle Attribute(Einschließlich Methode)Wörterbuch |
__doc__ |
Von Klassen und MethodendocstringKann erhalten werden. Wenn Sie nicht wissen, wie man es verwendet, aber es schwierig ist, den Quellcode oder die API-Dokumentation zu finden, können Sie es schnell sehen. |
Methodenname | Inhalt |
---|---|
__getattr__ |
Wird aufgerufen, wenn der Attributzugriff ausgeführt wird und das Zielattribut nicht vorhanden ist |
__getattribute__ |
Wird beim Zugriff auf Attribute immer aufgerufen |
__setattr__ |
Wird beim Zuweisen zu einem Attribut aufgerufen |
__delattr__ |
Wird beim Löschen eines Attributs aufgerufen(del obj.xxx ) |
__getstate__ |
Serialisierung von Objekten(Essiggurke)ich mache |
__setstate__ |
Wiederherstellung von serialisierten Objekten |
__str__ |
Methode zum Stringifizieren einer Klasse(Sogenannter toString) |
__repr__ |
Methode zur Ausgabe der Instanznotation(Typennotation und einige Mitglieder) |
__Str__
ähnelt __repr__
, aber __str__
dient dazu, dass Menschen den Inhalt der Variablen kennen (lesbar), und __repr__
dient dazu, zu überprüfen, ob die Variable vom beabsichtigten Typ ist ( Eindeutig) (Referenz). Es ist eine gute Verwendung, Form für Matrixvariablen usw. in __repr__
aufzunehmen, und Sie können überprüfen, ob die beabsichtigte Variable empfangen und verarbeitet wird. Es ist beabsichtigt, den Status der Instanz mit "str" zu formatieren, damit er von Menschen gelesen werden kann, wenn er an die Protokollkonsole ausgegeben wird.
Es gibt viele Fälle, in denen Sie mit dem Attribut "obj.xxx" anstelle der Zeichenfolge wie "obj [" xxx "]" zugreifen möchten. In diesem Fall ist das obige "getattr" usw. gültig. Unten Beispiel für die Implementierung in Soundcloud-Python Erhaltenes Objekt vom Typ Wörterbuch).
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()
Diese Technik kann verwendet werden, wenn Sie Attribute entsprechend der Antwort des anderen Teilnehmers dynamisch ändern möchten, z. B. einen Wrapper für WebAPI. Einzelheiten zur Verwendung finden Sie unter hier detailliert.
Attribute wie Instanz- / Klassendefinitionen können mit dem Modul "inspect" extrahiert werden.
>>> import inspect
>>> inspect.getmembers(some_instance)
Standardinstallation von Python 3.4.1, aber bis dahin gibt es keine Aufzählung.
Wenn Sie es verwenden möchten, installieren und verwenden Sie enum mit pip install enum34
.
import enum
class Color(enum.Enum):
Red = 10
Blue = 20
Yellow = 30
>>> Color.Red == Color.Red
True
>>> Color.Red == 10
False
#Dies ist falsch, da Enum nur ein Objekt vom Typ Enum ist. Es gibt auch ein IntEnum, das dies wahr macht
>>> Color.Red == Color(10)
True
#Sie können die entsprechende Aufzählung erstellen, indem Sie einen Wert an den Konstruktor übergeben
>>> Color.Red == Color["Red"]
True
#Beim Erstellen aus dem Namen[]Geben Sie den Namen mit an
>>> {Color.Red:"red", Color.Blue:"blue"}
{<Color.Blue: 20>: 'blue', <Color.Red: 10>: 'red'}
#Kann auch als Listenschlüssel verwendet werden
Wenn Sie die Zeichenfolge jedes Elements definieren möchten, können Sie sie zusammen mit __str__
verwenden. Dies ist nützlich, wenn Sie die Definition beim Anzeigen von Beschriftungen nicht verteilen möchten.
class Color(enum.Enum):
Red = 10
Blue = 20
Yellow = 30
def __str__(self):
if self.value == Color.Red.value:
return "rot"
elif self.value == Color.Blue.value:
return "Blau"
elif self.value == Color.Yellow.value:
return "Blau"
>>> print(Color.Red)
rot
Es gibt keine, aber es ist üblich, "" oder "_" am Anfang von privaten hinzuzufügen. Es gibt kein Konzept, das dem sogenannten Protected entspricht, wie es nur geerbten Klassen zeigen zu wollen. Was ist der Unterschied zwischen "" und "_"? Inwieweit sich dies von außen verbirgt, ändert sich.
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'
Wie oben erwähnt, können Sie mit einem Unterstrich wie gewohnt darauf zugreifen (es warnt Sie, wenn Sie ihn mit PEP überprüfen). Wenn Sie jedoch zwei Unterstriche haben, können Sie nur dann darauf zugreifen, wenn Sie "_Test__a" ausführen. Es macht es zu einer privaten Form (normalerweise unsichtbar).
Referenz
The meaning of a single- and a double-underscore before an object name in Python
Difference between _, __ and xx in Python
Sie können in Python keine Konstanten definieren. Da es sich bei den später beschriebenen Tupeln jedoch um unveränderliche Listen handelt, ist es möglich, Pseudokonstanten mithilfe dieser Liste zu erstellen (ich denke, dass const in Ordnung ist, wenn es eine unveränderliche Liste gibt ... ).
Hier in PEP8 sollten die Konstanten mit allem Kapital und Unterstrich verbunden sein, aber es gibt keine Überprüfung dafür.
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"
Das obige get_num
nimmt anscheinend ein Argument an, aber es ist im Wesentlichen eine Methode ohne Argumente.
Dann wird die Mitgliedsfunktion in derselben Klasse aufgerufen, indem das implizite erste Argument "self" und "cls" verwendet wird, so dass es "self.get_num ()" ist.
In Python gibt es ein Objekt namens Taple, das ungefähr eine "unveränderliche Liste" ist. Diese haben unterschiedliche Deklarationsmethoden.
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 kann aufgrund seiner Eigenschaften auch der Schlüssel zum Wörterbuch sein. Listen und Beispiele sind auch stark in Funktionen / Methoden eingebunden, die Argumente variabler Länge verarbeiten.
def out_with_tuple(a,b,*args):
# a,Argumente nach b werden in Tupel kombiniert
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})
Es ist leicht, sich "" als Zeiger vorzustellen, aber es stellt eine beliebige Anzahl von Argumenten dar und kann in ein Taple für "" und ein Wörterbuch für "**" gruppiert werden (kann zusammen verwendet werden).
Wenn der Aufrufer dann "*", "**" verwendet, kann der Listen- / Taple-Wert erweitert und als Argument übergeben werden.
>>> def out(a,b):
... print(a,b)
>>> out([1,2]) #Wenn Sie die Liste normal bestehen, natürlich 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) # *Erweitert die Elemente in der Liste und aus(1,2)Wird das gleiche sein wie anrufen
>>> out_with_dict(**{"a":1,"b":2})
(1, 2, {}) #Ähnlich wie oben**Erweitert die im Wörterbuch übergebenen Argumente
Der als Standardargument für eine Methode oder Funktion angegebene Wert muss unveränderlich sein. Dies ist normalerweise der Fall, daher gibt es kein Problem. Beachten Sie jedoch, dass leere Arrays veränderbar sind.
>>> 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] # !!!!!
Aus irgendeinem Grund ist der Wert in der Instanz von "b" vorgefüllt, was nichts mit "a" zu tun hat. Es sieht völlig kompliziert und bizarr aus, weshalb das Argument unveränderlich sein muss. Der Umfang des Standardarguments scheint mit dieser Methode / Funktion identisch zu sein. Wenn es nicht unveränderlich ist, verhält es sich wie eine globale Variable und verhält sich wie oben beschrieben.
In diesem Fall ist es daher erforderlich, zu einem Prozess zu wechseln, z. B. "Keine" als Standardargument und "[", wenn Keine. Wie bei Arrays ist Vorsicht geboten, wenn die Referenz als Anfangswert festgelegt wird.
Default Parameter Values in Python
Überladungen mit unterschiedlichen Argumenten und mit demselben Namen definiert können in Python nicht verwendet werden. Wenn Sie also eine Überladung verwenden möchten, müssen Sie das Standardargument verwenden oder den Typ des Arguments intern bestimmen, um es durch Verzweigung innerhalb einer Methode zu verarbeiten. Außerdem sind Klassenmethoden und Elementmethoden mit demselben Namen nicht zulässig.
Durch die Verwendung von singledispatch kann jedoch eine bedingte Verzweigung beseitigt und eine überladene Implementierung realisiert werden (Standard aus Python 3.4). unterstützt von).
In Python ist es möglich, Berechnungen mit Operatoren wie "+" und "-" (sogenanntes Operatorüberladen) zu implementieren (Referenz). ).
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
Es ist auch möglich, logische Operatoren wie "==" und ">" zu implementieren. Es ist jedoch ziemlich schwierig, alle Operatoren ohne Lücken zu definieren. Wenn es sich um ein numerisches Berechnungssystem handelt, ist es besser zu überprüfen, ob eine geeignete Bibliothek vorhanden ist, als sie selbst zu implementieren.
Ab Python3 (insbesondere ab Python3.5) können Typen für die Rückgabewerte von Argumenten und Funktionen geschrieben werden.
def greeting(name: str) -> str:
return 'Hello ' + name
Ab Python 3.6 können Sie Variablen auch Typinformationen hinzufügen (PEP 526).
my_string: str
my_dict: Dict[str, int] = {}
Dies wird als Typanmerkung bezeichnet, und obwohl zur Laufzeit kein Fehler ausgegeben wird, kann sie anhand dieser Informationen im Voraus überprüft werden. Zu den Überprüfungswerkzeugen gehört mypy, mit dem die Typintegrität vor der Ausführung überprüft werden kann. Siehe unten für Details.
Typisierte Welt beginnend mit Python
Darüber hinaus gibt es einige mit "@", die der Java-Annotation entsprechen. Dies ist jedoch keine Annotation, sondern ein "Decorator". Das Verhalten ist völlig anders und wirkt sich auf die Ausführung der Funktion aus. Wie der Name "dekorieren" andeutet, fungiert er als "Funktion, die eine Funktion umschließt".
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>
Referenz: Wie kann ich in Python eine Kette von Funktionsdekoratoren erstellen?
Das Obige ist dasselbe wie das Ausführen von makebold (makeitalic (hello)) (your_name)
(wird nacheinander vom Dekorator ausgeführt, der der Funktionsdefinition am nächsten liegt).
Wenn Sie vor dem Ausführen der Methode überprüfen möchten (Berechtigung usw. [Überschreibungen überprüfen]) (http://stackoverflow.com/questions/1167617/in-python-how-do-i-indicate-im-overriding-a-method] ), Usw.) oder wenn Sie die Verarbeitung vor und nach der Ausführung einfügen möchten (Messung der Ausführungszeit usw.). Außerdem soll functools.wrap
verhindern, dass die Informationen der Funktion durch die dekorierte Funktion anstelle der ursprünglichen Funktion durch Dekorieren ersetzt werden (hier. 20090427/1240838573)).
Es ist ziemlich schwierig, die Dekorateure für eine Methode zu gewinnen Daher ist es im Fall der Verwendung von Metaprogrammierung (z. B. Abrufen einer annotierten Methode und Ausführen dieser Methode) besser, sie auf Python3 zu aktualisieren und die Annotation zu verwenden.
In Python wird der Namespace (automatisch) für jede Datei abgeschnitten, ohne einen Namespace oder ein Paket zu deklarieren. Der Name des für jede Datei ausgeschnittenen Namespace ist gleichbedeutend mit dem Dateinamen. Wenn Sie also "TestClass" aufrufen, das in "package / test_class.py" definiert ist, müssen Sie "from package.test_class import TestClass" verwenden. Es gibt.
Da es in Dateieinheiten geschnitten wird, ist eine Importdeklaration erforderlich, wenn auf Dateien im selben Ordner verwiesen wird. Beachten Sie, dass der Ordner als Paket erkannt wird, wenn eine Datei mit dem Namen "__init __. Py" vorhanden ist (sie muss nicht aus Python3 stammen).
Wie bei Java können Sie, wenn Sie nach Paket- / Klassennamen importieren möchten (z. B. "aus Paketimport TestClass"), die Importanweisung der Datei in "__init __. Py" schreiben. Dies liegt daran, dass der Teil "from package" mit "__init __. Py" im Ordner geladen wird. Wenn hier also eine Importanweisung vorhanden ist, entspricht dies dem Importieren der Datei.
Beachten Sie, dass beim Importieren von Dateien, auf die gegenseitig verwiesen wird (A bezieht sich auf B und B bezieht sich auf A), dies zu einem Deadlock wird und nicht importiert werden kann. Um dies zu vermeiden, müssen einige Maßnahmen ergriffen werden, z. B. der Import innerhalb der erforderlichen Verarbeitung anstatt am Anfang der Datei (Referenz. Python)).
if __name__ ==" __main__ ":
kann den Prozess beschreiben, wenn er als Skript ausgeführt wird (wenn er mit python xxx.py
ausgeführt wird) (siehe [Top Level Script Environment](http: // docs). .python.jp / 2 / library / __ main __. html)).
if __name__ == "__main__":
print "Run Script"
Es spielt keine Rolle, ob dies die Datei ist, die die Klasse definiert, oder die Datei, die die Funktion definiert.
Wenn Sie daher die Operation der Klasse, die Sie definieren, für einen Moment überprüfen möchten, setzen Sie die obige if-Anweisung am Ende der Datei und schreiben Sie den Prozess zum Überprüfen der Operation unter python xxx.py Sie können dies überprüfen, indem Sie
einstellen. Das ist sehr praktisch.
In Python können Operationen in einem Array wie folgt ausgeführt werden.
>>> [ 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]
#Es ist auch möglich, Funktionen zu verwenden
>>>def calc_double(x):
>>> return x*2
>>> [ calc_double(x) for x in [1, 2, 3, 4, 5]]
[2, 4, 6, 8, 10]
Es funktioniert genauso wie integrierte Funktionen wie "Karte" und "Filter", aber in einigen Fällen ist es einfacher, mit besserer Lesbarkeit zu schreiben. In Python3 geben "map" und "filter" nicht die Liste selbst zurück, sondern es wird ein Iterator zurückgegeben. -list-in-python-3-x) Wenn Sie es also als Liste wie Python2 behandeln möchten, verwenden Sie die Listeneinschlussnotation, und wenn Sie es mit der nachfolgenden Verarbeitung vom Iterator verketten möchten, verwenden Sie map
/ filter
usw. Es ist einfach, beide Versionen zu unterstützen, wenn Sie es behalten.
Außerdem Es scheint, dass die Ausführungsgeschwindigkeit schnell ist.
Ab Python3.6 können asynchrone Iteratoren auch mit dieser Listeneinschlussnotation verarbeitet werden (PEP 530). ..
result = [i async for i in async_iter() if i % 2]
result = [await fun() for fun in async_funcs if await condition()]
In Python können Sie anonyme Funktionen mit Lambda erstellen.
>>> list(map(lambda x: x * 2, range(5)))
[0, 2, 4, 6, 8]
Oben wird "map" verwendet und die Funktion "Lambda x: x * 2" wird auf jeden Wert von "range (5)" angewendet.
Die von lambda
erstellte Funktion kann auch einer Variablen zugewiesen werden, und das Obige entspricht dem Folgenden.
>>> f = lambda x: x * 2
>>> list(map(f, range(5)))
[0, 2, 4, 6, 8]
In Kombination mit der obigen Listeneinschlussnotation wird auch die folgende Verarbeitung angewendet.
>>> f = lambda a, b: a + b
>>> [f(*z) for z in zip([1, 2, 3], [4, 5, 6])]
[5, 7, 9]
zip
ist eine praktische Funktion, die mehrere Arrays als Argumente verwendet und sie für jeden Index zusammenfügt.zip ([1, 2, 3], [4, 5, 6])
is[(1, 4), ( 2, 5), (3, 6)] ". Dies wird auf das Argument der Funktion
f using
*` erweitert und verarbeitet.
Python for-Anweisungen sind für jede Anweisung gleich und können standardmäßig nicht indiziert werden. Wenn Sie den Index in einer Schleifenanweisung verwenden möchten, gehen Sie wie folgt vor.
for index, value in enumerate(list):
print "index:" + index
Wenn Sie nur nach Index drehen möchten, können Sie auch wie folgt schreiben (Da es in Python keine "list.length" gibt, verwenden Sie "len (list)", um die Länge zu ermitteln).
for index in range(len(list)):
print "index:" + index
Als praktische Eigenschaft können Sie in der Python for-Anweisung else festlegen (obwohl while möglicherweise häufiger verwendet wird).
child = "Bob"
for c in ["Alice", "Tom", "Ann", "Cony"]:
if c == child:
break
else:
print("{} is not here.".format(child))
Der durch "else" definierte Prozess wird verarbeitet, wenn "break" nicht ausgeführt wird. Daher kann es verwendet werden, um die Verarbeitung zu beschreiben, wenn die Erkennung nicht in der Schleife durchgeführt werden kann.
Da Python keine switch-Anweisung hat, wird stattdessen if-else verwendet. Nun, Sie könnten denken, aber Python hat eine Einrückung und wenn es ziemlich sauber ist, ist dies kein allzu großes Problem.
Aus diesem Grund können Sie auch denken, dass Sie in Python keine einzeilige if-Anweisung (sogenannter ternärer Operator) schreiben können, aber in Python 2.5 oder höher können Sie wie folgt schreiben ([PEP 308-] - Bedingte Ausdrücke](siehe http://legacy.python.org/dev/peps/pep-0308/).
>>> test = 1
>>> "test eq 1" if test == 1 else "test not eq 1"
'test eq 1'
Ab Python3.5 kann die asynchrone Verarbeitung einfach mit der Syntax "async" / "await" implementiert werden (obwohl es zuvor möglich war, mit "asyncio" als Grammatik zu implementieren Implementiert). Wenn ein bestimmter kontinuierlicher Prozess (im Folgenden "Aufgaben") in mehreren Prozessen verarbeitet wird, kann er wie folgt geschrieben werden.
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)
Das Ausführungsergebnis lautet wie folgt (* Natürlich ist das Ergebnis bei jeder Ausführung anders).
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
Weitere Informationen finden Sie im folgenden Artikel.
Asynchrone Verarbeitung in Python: Asyncio-Reverse-Referenz
Darüber hinaus wurde es möglich, einen asynchronen Iterator einfacher mit "Yield" aus Python 3.6 ([PEP 525](https://docs.python.org/3.6/whatsnew/3.6.html# ") zu erstellen. 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)
In Python gibt es eine Site namens PyPI, auf der Pakete gehostet werden. Durch die Veröffentlichung des hier erstellten Pakets kann es von anderen Personen mit Pip-Installation usw. häufig verwendet werden. Sie können es bekommen (wie Maven in Java, rubygems.org in Ruby, Nuget in .NET).
Wenn Sie bei dieser Methode normal suchen, wird die alte Methode häufig abgefangen. Die neueste Upload-Methode finden Sie im Folgenden.
Veröffentlichen Sie die in Python erstellte Bibliothek in PyPI
Siehe auch unten für etwas anderes als die hier aufgeführten. [Python] 10 echte Fallstricke von Python, die zu detailliert sind, um sie zu vermitteln
Recommended Posts