Heim > Backend-Entwicklung > Python-Tutorial > Zusammenfassung einiger Tipps für fortgeschrittene Programmierung in Python

Zusammenfassung einiger Tipps für fortgeschrittene Programmierung in Python

伊谢尔伦
Freigeben: 2017-06-28 13:29:40
Original
1444 Leute haben es durchsucht

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]
Nach dem Login kopieren

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]
Nach dem Login kopieren

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]
Nach dem Login kopieren
  • 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:


Dies ist etwas effizienter als das Listenverständnis, also transformieren wir den Code noch einmal:
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
Nach dem Login kopieren

Sofern keine besonderen Gründe vorliegen, sollten Sie in Ihrem Code immer Generatorausdrücke verwenden. Sofern Sie es jedoch nicht mit sehr großen Listen zu tun haben, werden Sie keinen signifikanten Unterschied feststellen.
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]
Nach dem Login kopieren

Das folgende Beispiel verwendet die Funktion zip(), um Elemente in zwei oder mehr Listen gleichzeitig zu verarbeiten:



Sehen wir uns eine Ableitung einer Liste zweier Ordnung an
alist = [&#39;a1&#39;, &#39;a2&#39;, &#39;a3&#39;]
blist = [&#39;1&#39;, &#39;2&#39;, &#39;3&#39;]
 
for a, b in zip(alist, blist):
 print a, b
 
# a1 1
# a2 2
# a3 3
Nach dem Login kopieren
Beispiel für das Durchlaufen eines Verzeichnisses

:

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(&#39;C:\Users\XXX\Downloads\Test&#39;):
 print name
Nach dem Login kopieren
Dekoratoren

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.


Die Syntax Sugar @ identifiziert den Dekorator.
def timethis(func):
 &#39;&#39;&#39;
 Decorator that reports the execution time.
 &#39;&#39;&#39;
 pass
 
@timethis
def countdown(n):
 while n > 0:
 n -= 1
Nach dem Login kopieren

好了,让我们回到刚才的例子。我们将用装饰器做一些更典型的操作:

import time
from functools import wraps
 
def timethis(func):
 &#39;&#39;&#39;
 Decorator that reports the execution time.
 &#39;&#39;&#39;
 @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)
 
# (&#39;countdown&#39;, 0.006999969482421875)
Nach dem Login kopieren

当你写下如下代码时:

@timethis
def countdown(n):
Nach dem Login kopieren

意味着你分开执行了以下步骤:

def countdown(n):
...
countdown = timethis(countdown)
Nach dem Login kopieren

装饰器函数中的代码创建了一个新的函数(正如此例中的wrapper函数),它用 *args 和 **kwargs 接收任意的输入参数,并且在此函数内调用原函数并且返回其结果。你可以根据自己的需要放置任何额外的代码(例如本例中的计时操作),新创建的包装函数将作为结果返回并取代原函数。

@decorator
def function():
 print("inside function")
Nach dem Login kopieren

当编译器查看以上代码时,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()
Nach dem Login kopieren

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!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage