Python-Muster, die für die Welt freigegeben und später überprüft wurden

Hallo. Ich bin Nabeta, eine Softwareentwicklerin in der Infrastrukturgruppe. Es ist die Nacht des 11. (22:00), also schreibe ich diesen Artikel in Eile. Ich werde weiter schreiben, nachdem ich es bis zur letzten Minute gefunden habe. Drücke so ruhig auf die Tastatur, wie du keine Zeit hast, Luke.

Geben Sie die höchste Priorität frei

Grundsätzlich wartet die Veröffentlichung nur, wenn sie ziemlich gefährlich ist. Ich denke, dass jeder Erfahrung darin hat, sie als "Nein!" An die Welt zu senden. Außerdem konnte ich mir nicht die Zeit nehmen, den vorhandenen Code zu überarbeiten, und ich schrieb einen seltsamen Code, weil ich nicht in der Lage war. Danach werde ich über einige der Muster nachdenken, die ich behoben habe. Wie auch immer, ich habe keine Zeit, also lasst uns unser Bestes tun, um den Platz für Artikel zu füllen!

Werfen Sie beim Erstellen eines Objekts keine \ _ \ _ Daten \ _ \ _ ein

sample1.py


class Api(object):
    def __init__(self, init_data):
        self.init_data = init_data
        self.prepare()
        
    def prepare(self)
        for k, v in self.init_data.items():
            self.__data__[k] = v

init_data ist ein Wörterbuch. Selbst wenn das Innere von "init_data", das von "Api" gegessen wird, geändert wird, muss ich die Implementierung von "Api" nicht ändern, und ich habe es oft verwendet, während ich dachte, es sei metaprogrammierend und cool. Wenn Sie es lesen, müssen Sie die interne Implementierung von init_data und anderer Klassen und Methoden kennen, die die Verwendung von Api-Objekten implementieren, was ziemlich schmerzhaft ist. Wenn Sie "init_data" mit Code generieren, ist das Lesen sehr unangenehm.

Es war später einfacher zu lesen, wenn ich ein Wörterbuch vorbereitete, das alle Schlüssel und Werte definierte, oder eine Klasse erstellte, die sie umschließt.

sample2.py


class Api(object):
    def __init__(self, init_data):
        self.name = name
        self.a = init_data['a']
        self.b = init_data['b']
        ...

Verwenden Sie nach der for, while-Schleife nichts anderes

Mit Python können Sie nach einem Block von Schleifen ein "else" setzen.

sample3.py


for i in range(5):
    print('Count %d' % i)
else:
    print('ELSE BLOCK!!')

Dies wird unmittelbar nach dem Ende der Schleife ausgeführt. Es gibt überhaupt kein "anderes" Gefühl. Außerdem wird dieser übersprungen, wenn "Pause" gemacht ist, so dass ich die Bedeutung von "Sonst" nicht mehr verstehe.

sample4.py


>>> for i in range(5):
...     if i == 3:
...         break
...     print(i)
... else:
...     print('ELSE!') # unreachable!
0
1
2

Dann habe ich mich gefragt, wofür dieser Typ gedacht ist, aber ich denke, es wäre ein wenig effektiv, wenn man etwas verarbeitet, das die Bedingungen in einer Schleife erfüllt. In diesem Fall ist es jedoch einfacher zu lesen, wenn Sie eine Funktion für diesen Zweck erstellen. Der Name "else" ist irreführend und sollte nicht verwendet werden.

Im Folgenden wird das Ergebnis gescannt und zurückgegeben, ob Sie das Gesuchte gefunden haben oder nicht.

sample5.py


#Das ist besser
def power_up_if(users):
    found = False
    for user in users:
        if user == 42: #Kehre zurück, sobald der gesuchte Zustand gefunden wurde
            found = True
            break
    return user, found

users = [1,2,3,41,42,5]
uid, found = power_up_if(users)
if found:
    print('uid:', uid, 'is power up!')

Schreiben Sie nicht so, als ob die Standardargumente dynamisch festgelegt würden

Sie möchten selten nicht statische Schlüsselwortargumente als Standardwerte für Funktionen und Methoden verwenden.

sample6.py


>>> def log_out(msg, when=datetime.datetime.now()):
...       print('%s %s ' % (when, msg))
... 
... log_out('Good bye!!')
... log_out('Good bye!!')
2016-12-11 21:21:20.928785 Good bye!!
2016-12-11 21:21:20.928785 Good bye!!

Ich denke, dies ist eine Spezifikation, die Sie sicherlich kennen (Schritt für Schritt), wenn Sie Python so schreiben, wie es ist. Das Standardargument wird nur einmal ausgewertet, wenn die Funktion definiert ist. Mit anderen Worten, der Wert des Standardarguments wird beim Laden des Moduls bestimmt und nie wieder ausgewertet. Ich bin auch auf diese Spezifikation getreten und habe viel Geld bezahlt, um das Problem zu lösen. Als Workaround

sample7.py


>>> def log_out(msg, when=None):
...     """Ausgabeprotokoll mit Zeitstempel
...
...     Args:
...         msg:Nachricht protokollieren
...         when:Datum und Uhrzeit der Protokollausgabe. Wenn nicht, stellen Sie das aktuelle Datum und die aktuelle Uhrzeit ein.
...     """
...     when = datetime.datetime.now() if when is None else when
...     print('%s %s ' % (when, msg))

>>> log_out('hoge')
2016-12-11 21:28:58.293714 hoge

>>> log_out('bye')
2016-12-11 21:29:02.566320 bye

>>> log_out('bye', datetime.datetime(2016,11,1))
2016-11-01 00:00:00 bye

Ich denke, es ist besser, den Wert des Standardarguments auf "None" zu setzen und ihn durch die Redewendung "when = datetime.datetime.now () zu bestimmen, wenn wann None else when" in der Funktion ist. Wenn ja, werde ich es einstellen, und wenn nicht, werde ich es hier tun.

Wählen Sie öffentlich statt privat

Soweit ich weiß, gibt es in Python kein absolutes Privatleben.

sample8.py


>>> class A(object):
...     def __aa(self):
...         print('private')
>>>
>>>
>>> a = A()
>>> a._A__aa()
private
>>> class A(object):
...     def __init__(self, a):
...         self.__a = a

>>>
>>> a = A(123)
>>> print(a.__dict__)
{'_A__a': 123}

Daher kann jeder, der die Konvertierungsregeln des Compilers wie oben beschrieben kennt, auf die privaten Attribute zugreifen. Da jedoch privat und öffentlich als Sichtbarkeit der Klasse existieren, gibt es keinen Fall, in dem der oben genannte Zugriff tatsächlich erforderlich ist, und wenn ja, denke ich, dass ich einen Fehler im Design gemacht habe.

Der Grund, warum jeder wie die Öffentlichkeit darauf zugreifen kann, ist, dass es bereits auf der Theorie der Sexualität basiert. Ich frage mich, ob Python so süß ist, aber Sie denken wahrscheinlich, dass die Vorteile der Öffentlichkeit höher sind als die Vorteile der Privatheit. Ich bin mir nicht sicher, ob dies korrekt ist, aber in letzter Zeit beschränken sich die Fälle, in denen es privat gemacht wird (mit dem Attribut __start), hauptsächlich auf Folgendes.

sample9.py


>>> class Student(object):
...     def __init__(self):
...         self.__name = "Anonymous"
...
...     def get_name(self):
...         return self.__name
...
... class ChildStudent(Student):
...     def __init__(self):
...         super().__init__()
...         self._name = "Child"
...
... c = ChildStudent()
... print(c.get_name(), c._name)
Anonymous Child

Definieren Sie keine get- oder set-Methoden

Dies bedeutet, dass das Definieren niemals schlecht oder ähnliches ist und Sie keine expliziten Getter oder Setter implementieren müssen.

sample10.py


>>> class OtherLangStyle(object):
...     def __init__(self, val):
...         self._val = val
...
...     def get_val(self):
...         return self._val
...
...     def set_val(self, new_val):
...         self._val = new_val

>>> ols = OtherLangStyle(1)
>>> ols.get_val()
1
>>> ols.set_val(2)
>>> ols.get_val()
2
>>> ols.set_val(ols.get_val() + 2)
>>> ols.get_val()
4

Nicht wie Python. Ich fühle mich wie es eingekapselt ist. .. .. Wie oben erwähnt, glaube ich nicht, dass es ein Problem gibt, wenn ich es einfach in der Öffentlichkeit implementiere, und ich implementiere es immer in der Öffentlichkeit.

sample11.py


>>> class PythonStyle(object):
...     def __init__(self, val):
...         self.val = val
... ps = PythonStyle(1)
... ps.val = 3
>>> ps.val
3
>>> ps.val += 4
>>> ps.val
7

Wenn Sie einen Hook für dieses Attribut benötigen

Wenn Sie später einen Hook benötigen, hat Python eine super nützliche Sache namens "@ property" -Dekorator, und Sie können einfach "@ property", Setter, implementieren.

sample12.py


>>> class Student(object):
...     def __init__(self, name, score):
...         self._name = name
...         self._score = score
...
...     @property
...     def score(self):
...         return self._score
...
...     @score.setter
...     def score(self, score):
...         before = self.score
...         self._score = score
...         self.notify_score_up(before)
...
...     @property
...     def name(self):
...         return self._name
...
...     def notify_score_up(self, before):
...         print('%s score is up. %d to %d.' %
...               (self.name, before, self.score))
...
... s = Student('nabetama', 0)
... s.score = 3
nabetama score is up. 0 to 3.

Wenn Sie den Setter so implementieren, können Sie auch den übergebenen Wert überprüfen!

Verwenden Sie beim Erstellen von Dekoratoren functools.wraps

Beim Schreiben von Python möchte jeder mindestens einmal einen Dekorateur schreiben. Wenn Sie die Bearbeitungszeit einer Funktion wissen möchten

sample13.py


>>> def checktime(func):
...     @wraps(func)
...     def wrapper(*args, **kwargs):
...         import time
...         start = time.time()
...         res = func(*args, **kwargs)
...         end = time.time() - start
...         print('--------------------------------------------------')
...         print(end)
...         print('--------------------------------------------------')
...         return res
...     return wrapper
...
... @checktime
... def wait1():
...     time.sleep(1)
...     print('owata')
...
... wait1()
owata
... print(wait1)
<function wait1 at 0x1119a0d90>    #wait1 und seine Metadaten werden zurückgegeben
--------------------------------------------------
1.003669023513794
--------------------------------------------------

Ich bereite einen Dekorateur wie diesen vor und mache so etwas wie eine Funktion zu verpacken. Der Grund für die Verwendung von functools.wraps ist, dass der vom Dekorator zurückgegebene Wert (dh die Funktion) sich nicht selbst als aufrufende Methode interpretiert. Versuchen Sie, wraps () aus dem obigen Code zu entfernen.

sample14.py


>>> def checktime(func):
...     def wrapper(*args, **kwargs):
...         import time
...         start = time.time()
...         res = func(*args, **kwargs)
...         end = time.time() - start
...         print('--------------------------------------------------')
...         print(end)
...         print('--------------------------------------------------')
...         return res
...     return wrapper
...
... @checktime
... def wait1():
...     time.sleep(1)
...     print('owata')
...
... wait1()
... print(wait1)
owata
--------------------------------------------------
1.0004959106445312
--------------------------------------------------
<function checktime.<locals>.wrapper at 0x1118b5ae8>  #...?

Sie können functools.wraps verwenden, um die Metadaten der internen Funktion in die externe Funktion zu kopieren, selbst wenn sie in einen Dekorator eingeschlossen sind.

Verwenden Sie integrierte Algorithmen und Datenstrukturen

Wörterbuch sortieren

Python-Wörterbücher werden nicht sortiert. In realen Programmen gibt es jedoch Situationen, in denen Sie in der Reihenfolge sortieren möchten, in der die Schlüssel im Wörterbuch eingefügt werden. In einem solchen Fall ist collection.OrderedDict praktisch.

sample15.py


>>> names = ['s', 'p', 'l', 'g']
>>> o = OrderedDict()
>>> for name in names:
...     o[name] = 1

>>> o
OrderedDict([('s', 1), ('p', 1), ('l', 1), ('g', 1)])

>>> oo = dict()
>>> for name in names:
...     oo[name] = 1
>>> oo
{'p': 1, 'l': 1, 'g': 1, 's': 1}

Standardwörterbuch

Wenn der Schlüssel nicht vorhanden ist, wird ein vorgegebener Standardwert zurückgegeben.

sample16.py



>>> from collections import defaultdict
>>> rec = defaultdict(int)
>>> rec['ore']
0
>>> rec
defaultdict(<class 'int'>, {'ore': 0})

Bonus

In letzter Zeit schreibe ich gerne Dokumente mit Sphinx, aber in .git / hooks

sample.sh


#!/bin/sh
#
make html

Wenn Sie dies tun, bin ich froh, dass der HTML-Build jedes Mal automatisch ausgeführt wird.

Zusammenfassung

Ich denke, es wird nicht viel, aber wenn ich das Python-Projekt, das ich dieses Jahr geschrieben habe, zurücklese, wird es herauskommen. Es wird mehr herauskommen und es ist der 12. gewesen, also werde ich einen Pinsel darauf legen. Es gibt viele andere Dinge, also schreibe ich es auf meinen eigenen Blog.

Ich habe es erwähnt, sobald ich darauf gekommen bin, aber ich werde mich 2016 verabschieden und denke, dass ich später über diesen Artikel nachdenken werde.

Recommended Posts

Python-Muster, die für die Welt freigegeben und später überprüft wurden
Begrüßen Sie die Welt mit Python mit IntelliJ
PHP- und Python-Beispiele, die die ChatWork-API treffen
Ich hatte das Gefühl, dass ich den Python-Code nach C ++ 98 portiert habe.
Die Einstellung, die Programmierer haben sollten (The Zen of Python)
[C / C ++] Übergeben Sie den in C / C ++ berechneten Wert an eine Python-Funktion, um den Prozess auszuführen, und verwenden Sie diesen Wert in C / C ++.
Jedi-vim-Verknüpfungsbefehl, mit dem Sie auf die Definitionsquelle und das Definitionsziel in Python verweisen können
Eine Geschichte, die es einfach macht, den Wohnbereich mit Elasticsearch und Python abzuschätzen
[Python] Ein Programm, um die Anzahl der Äpfel und Orangen zu ermitteln, die geerntet werden können
Erstellen Sie eine Python-Umgebung und übertragen Sie Daten auf den Server
Ich möchte die Natur von Python und Pip kennenlernen
Ich habe versucht, die Unterschiede zwischen Java und Python aufzuzählen
So schreiben Sie eine Meta-Klasse, die sowohl Python2 als auch Python3 unterstützt
Wir haben eine Erweiterung veröffentlicht, mit der Sie Xarray-Daten wie eine Python-Datenklasse definieren können.
Bestimmen Sie das Datums- und Uhrzeitformat mit Python und konvertieren Sie es in Unixtime
Die Geschichte, dass die Version von Python 3.7.7 nicht an Heroku angepasst wurde
Bestehen und Studieren der Python 3 Engineer-Zertifizierungsgrundprüfung
Reguläre Ausdrücke, die in Python leicht und solide zu erlernen sind
So erhalten Sie mithilfe der Mastodon-API Follower und Follower von Python
[Einführung in Python] Ich habe die Namenskonventionen von C # und Python verglichen.
[Python] So erhalten Sie den ersten und den letzten Tag des Monats
So stellen Sie fest, dass in Python3 ein Kreuzschlüssel eingegeben wurde
Verwenden Sie Python auf Raspberry Pi 3, um die LED zu beleuchten (Hello World)
Schreiben Sie ein Programm, das das Programm missbraucht und 100 E-Mails sendet
Über den Fehler, dass Anaconda Numpy und Scipy nicht importieren kann
Ein Skript, das 0, 1 an die erste Python-Primzahl zurückgibt
Der Weg zur Installation von Python und Flask auf einem Offline-PC
Eine Kurzanleitung zu PyFlink, die Apache Flink und Python kombiniert
Konvertieren Sie das Ergebnis von Python Optparse, um es zu diktieren und zu verwenden
Überprüfung der Theorie, dass "Python und Swift ziemlich ähnlich sind"
Stellen Sie sicher, dass Python eine Zeichenfolge in int konvertieren / konvertieren kann
Der Versuch, Segmentbäume Schritt für Schritt zu implementieren und zu verstehen (Python)
[Einführung in Python] Verwendung des Booleschen Operators (und ・ oder ・ nicht)
[Python] Ein Hinweis, dass ich das Verhalten von matplotlib.pyplot zu verstehen begann
[Python] Ein Programm, das den Inhalt der Liste nach links dreht
So zeigen Sie Bytes in Java und Python auf die gleiche Weise an