In diesem Artikel werden hauptsächlich einige fortgeschrittene Programmierkenntnisse in Python vorgestellt, einschließlich wichtiger fortgeschrittener Wissenspunkte wie Tutoren und Dekorateure, die allesamt notwendige Grundkenntnisse für ein tiefgreifendes Erlernen der Python-Entwicklung sind
Text:
Dieser Artikel zeigt einige erweiterte Python-Designstrukturen und deren Verwendung. Bei der täglichen Arbeit können Sie die geeignete Datenstruktur entsprechend Ihren Anforderungen auswählen, z. B. Anforderungen an eine schnelle Durchsuchbarkeit, Anforderungen an Datenkonsistenz oder Anforderungen an Indizes usw. Sie können auch verschiedene Datenstrukturen entsprechend kombinieren und so eine logische und logische Struktur erstellen leicht verständliches Datenmodell. Die Datenstrukturen von Python sind syntaktisch sehr intuitiv und bieten eine große Anzahl optionaler Operationen. Dieser Leitfaden versucht, die meisten der am häufigsten verwendeten Datenstrukturkenntnisse zusammenzustellen und eine Diskussion über deren beste Verwendung zu liefern.
Comprehensions
Wenn Sie Python schon lange verwenden, sollten Sie zumindest schon einmal von List Comprehensions gehört haben. Dies ist eine Möglichkeit, die for-Schleife, den ifAusdruck und die Zuweisungsanweisung in einer einzigen Anweisung zusammenzufassen. Mit anderen Worten: Sie können eine Liste mithilfe eines Ausdrucks zuordnen oder filtern.
Ein Listenverständnis enthält die folgenden Teile:
Eine Eingabesequenz
Eine Variable, die die Mitglieder der Eingabesequenz darstellt
Ein optionaler Behauptungsausdruck
Ein Ausgabeausdruck, der Mitglieder der Eingabesequenz, die den Behauptungsausdruck erfüllen, in Mitglieder der Ausgabelistenformel umwandelt
Zum Beispiel müssen wir eine neue Sequenz aus einer Eingabeliste generieren, indem wir alle ganzen Zahlen größer als 0 quadrieren. Sie könnten schreiben:
num = [1, 4, -5, 10, -7, 2, 3, -1] filtered_and_squared = [] for number in num: if number > 0: filtered_and_squared.append(number ** 2) print filtered_and_squared # [1, 16, 100, 4, 9]
Ganz einfach, oder? Dies wären jedoch 4 Codezeilen, zwei Verschachtelungsebenen und eine völlig unnötige Anhängeoperation. Wenn Sie Filter-, Lambda- und Kartenfunktionen verwenden, kann der Code stark vereinfacht werden:
num = [1, 4, -5, 10, -7, 2, 3, -1] filtered_and_squared = map(lambda x: x ** 2, filter(lambda x: x > 0, num)) print filtered_and_squared # [1, 16, 100, 4, 9]
Nun, auf diese Weise wird der Code in horizontaler Richtung erweitert. Können wir den Code also weiter vereinfachen? Die Listenableitung kann uns die Antwort geben:
num = [1, 4, -5, 10, -7, 2, 3, -1] filtered_and_squared = [ x**2 for x in num if x > 0] print filtered_and_squared # [1, 16, 100, 4, 9]
Der Iterator durchläuft jedes Mitglied der Eingabesequenz num x
Das Behauptung bestimmt, ob jedes Mitglied größer als Null ist
Wenn das Mitglied größer als Null ist, wird es dem Ausgabeausdruck übergeben und wird nach der Quadrierung ein Mitglied der Ausgabeliste.
Das Listenverständnis ist in einer Liste gekapselt, sodass offensichtlich sofort eine neue Liste generiert wird. Es gibt nur einen Typfunktionsaufruf und keinen impliziten Aufruf der Lambda-Funktion. Das Listenverständnis verwendet einen regulären Iterator, einen Ausdruck und einen if-Ausdruck, um die optionalen Parameter zu steuern.
Andererseits kann das Listenverständnis auch einige negative Auswirkungen haben, das heißt, die gesamte Liste muss auf einmal in den Speicher geladen werden. Dies ist für das oben angegebene Beispiel kein Problem, auch wenn dies der Fall ist Mehrmals erweitert. Nichts davon ist ein Problem. Aber das Limit wird immer erreicht und der Speicher wird immer aufgebraucht sein.
Als Reaktion auf die oben genannten Probleme kann Generator (Generator) es sehr gut lösen. Der Generatorausdruck lädt nicht die gesamte Liste auf einmal in den Speicher, sondern generiert einen Generatorobjektor, sodass jeweils nur ein Listenelement geladen wird. Generatorausdrücke haben fast die gleiche Syntaxstruktur wie Listenverständnisse. Der Unterschied besteht darin, dass Generatorausdrücke in Klammern statt in eckigen Klammern stehen:
num = [1, 4, -5, 10, -7, 2, 3, -1] filtered_and_squared = ( x**2 for x in num if x > 0 ) print filtered_and_squared # <generator object <genexpr> at 0x00583E18> for item in filtered_and_squared: print item # 1, 16, 100 4,9
num = [1, 4, -5, 10, -7, 2, 3, -1] def square_generator(optional_parameter): return (x ** 2 for x in num if x > optional_parameter) print square_generator(0) # <generator object <genexpr> at 0x004E6418> # Option I for k in square_generator(0): print k # 1, 16, 100, 4, 9 # Option II g = list(square_generator(0)) print g # [1, 16, 100, 4, 9]
Das folgende Beispiel verwendet die Funktion zip(), um Elemente in zwei oder mehr Listen gleichzeitig zu verarbeiten:
alist = ['a1', 'a2', 'a3'] blist = ['1', '2', '3'] for a, b in zip(alist, blist): print a, b # a1 1 # a2 2 # a3 3
import os def tree(top): for path, names, fnames in os.walk(top): for fname in fnames: yield os.path.join(path, fname) for name in tree('C:\Users\XXX\Downloads\Test'): print name
Dekoratoren bieten uns eine Möglichkeit, vorhandene Funktionen oder eine gültige Methode hinzuzufügen einer Funktion einer Klasse. Klingt es sehr nach dem Konzept der aspektorientierten Programmierung (Aspect-Oriented Programming) in Java? Beide sind einfach und Dekorateure sind leistungsfähiger. Wenn Sie beispielsweise einige spezielle Vorgänge (z. B. Sicherheit, Nachverfolgung, Sperrung usw.) an den Ein- und Ausstiegspunkten einer Funktion ausführen möchten, können Sie Dekoratoren verwenden.
Ein Dekorator ist eine spezielle Funktion, die eine andere Funktion umschließt: Die Hauptfunktion wird aufgerufen und ihr Rückgabewert wird an den Dekorator übergeben, der dann eine Ersatzfunktion zurückgibt, die die Hauptfunktion und andere Teile des Programms umschließt siehe wird diese Wrapper-Funktion sein.
def timethis(func): ''' Decorator that reports the execution time. ''' pass @timethis def countdown(n): while n > 0: n -= 1
好了,让我们回到刚才的例子。我们将用装饰器做一些更典型的操作:
import time from functools import wraps def timethis(func): ''' Decorator that reports the execution time. ''' @wraps(func) def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(func.name, end-start) return result return wrapper @timethis def countdown(n): while n > 0: n -= 1 countdown(100000) # ('countdown', 0.006999969482421875)
当你写下如下代码时:
@timethis def countdown(n):
意味着你分开执行了以下步骤:
def countdown(n): ... countdown = timethis(countdown)
装饰器函数中的代码创建了一个新的函数(正如此例中的wrapper函数),它用 *args 和 **kwargs 接收任意的输入参数,并且在此函数内调用原函数并且返回其结果。你可以根据自己的需要放置任何额外的代码(例如本例中的计时操作),新创建的包装函数将作为结果返回并取代原函数。
@decorator def function(): print("inside function")
当编译器查看以上代码时,function()函数将会被编译,并且函数返回对象将会被传给装饰器代码,装饰器将会在做完相关操作之后用一个新的函数对象代替原函数。
装饰器代码是什么样的?大部分的例子都是将装饰器定义为函数,而我发觉将装饰器定义成类更容易理解其功能,并且这样更能发挥装饰器机制的威力。
对装饰器的类实现唯一要求是它必须能如函数一般使用,也就是说它必须是可调用的。所以,如果想这么做这个类必须实现call方法。
这样的装饰器应该用来做些什么?它可以做任何事,但通常它用在当你想在一些特殊的地方使用原函数时,但这不是必须的,例如:
class decorator(object): def init(self, f): print("inside decorator.init()") f() # Prove that function definition has completed def call(self): print("inside decorator.call()") @decorator def function(): print("inside function()") print("Finished decorating function()") function() # inside decorator.init() # inside function() # Finished decorating function() # inside decorator.call()
Das obige ist der detaillierte Inhalt vonZusammenfassung einiger Tipps für fortgeschrittene Programmierung in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!