Heim >Backend-Entwicklung >Python-Tutorial >Einige Programmiertipps für Python-Anfänger

Einige Programmiertipps für Python-Anfänger

高洛峰
高洛峰Original
2016-10-17 13:23:231264Durchsuche

Python ist eine sehr ausdrucksstarke Sprache. Es stellt uns eine riesige Standardbibliothek und viele integrierte Module zur Verfügung, die uns helfen, unsere Arbeit schnell zu erledigen. Viele Menschen verlieren jedoch möglicherweise den Überblick über die bereitgestellten Funktionen, nutzen die Vorteile der Standardbibliothek nicht voll aus, legen zu viel Wert auf einzeilige Skripte und verstehen die Grundstruktur von Python falsch. Dieser Artikel ist eine nicht erschöpfende Liste einiger Fallstricke, in die neue Python-Entwickler geraten können.

1. Ich kenne die Python-Version nicht

Dies ist eine wiederkehrende Frage bei StackOverflow. Viele Leute können Code schreiben, der auf einer Version perfekt funktioniert, aber sie haben eine andere Version von Python auf ihrem System installiert. Stellen Sie sicher, dass Sie wissen, welche Python-Version Sie verwenden.

Sie können die Python-Version mit dem folgenden Code überprüfen:

[pythontab@testServer]$ python --version
Python 2.7.10
[pythontab@testServer]$ python --V
Python 2.7.10

Beide der oben genannten Methoden sind möglich

2 Der Versionsmanager

pyenv ist ein hervorragendes Tool zum Verwalten verschiedener Python-Versionen, funktioniert aber leider nur auf *nix-Systemen. Auf Mac-Systemen können Sie es einfach über brew install pyenv installieren, und unter Linux gibt es auch einen automatischen Installer.

3. Süchtig nach einzeiligen Programmen

Viele Menschen sind begeistert von der Aufregung, die einzeilige Programme mit sich bringen. Selbst wenn ihre Einleitungslösung weniger effizient ist als eine Mehrleitungslösung, werden sie damit prahlen.

Ein Einzeiler in Python bedeutet im Wesentlichen eine komplexe Ableitung mit mehreren Ausdrücken. Zum Beispiel:

l = [m for a, b in zip(this, that) if b.method(a) != b for m in b if not m.method(a, b) and reduce(lambda x, y: a + y.method(), (m, a, b))]

Um ehrlich zu sein, habe ich mir das obige Beispiel ausgedacht. Aber ich sehe viele Leute, die ähnlichen Code schreiben. Ein solcher Code wird nach einer Woche unverständlich. Wenn Sie etwas Komplexeres tun möchten, beispielsweise einfach ein Element zu einer Liste hinzufügen oder auf der Grundlage einer Bedingung festlegen, werden Sie wahrscheinlich einen Fehler machen.

Einzelne Codezeilen sind keine Errungenschaft, sie mögen zwar flexibel aussehen, aber sie sind keine Errungenschaft. Stellen Sie sich vor, es wäre, als würden Sie Ihr Haus putzen und alles in Ihren Schrank stopfen. Guter Code sollte sauber, leicht lesbar und effizient sein.

4. Eine Sammlung falsch initialisieren

Dies ist ein subtileres Problem, das Sie überraschen kann. Mengenverständnisse sind Listenverständnissen sehr ähnlich.

 
>>> { n for n in range(10) if n % 2 == 0 }
{0, 8, 2, 4, 6}
>>> type({ n for n in range(10) if n % 2 == 0 })

Das Obige ist ein Beispiel für die Mengenableitung. Eine Sammlung ist wie eine Liste und ein Container. Der Unterschied besteht darin, dass eine Menge keine doppelten Werte enthalten kann und ungeordnet ist. Leute, die sich mit Mengenableitungen befassen, denken oft fälschlicherweise, dass {} eine leere Menge initialisiert. Dies ist jedoch nicht der Fall, es initialisiert ein leeres Wörterbuch.

>>> {}
{}
>>> type({})

Wenn Sie eine leere Sammlung initialisieren möchten, können Sie einfach die Methode set() aufrufen.

>>> set()
set()
>>> type(set())

Beachten Sie, dass eine leere Menge durch set() dargestellt wird, eine Menge, die einige Elemente enthält, jedoch durch geschweifte Klammern dargestellt werden muss, die die Elemente umgeben.

>>> s = set()
>>> s
set()
>>> s.add(1)
>>> s
{1}
>>> s.add(2)
>>> s
{1, 2}

Dies ist kontraintuitiv, da Sie so etwas wie set([1, 2]) erwarten.

5. Missverständnis von GIL

GIL (Global Interpreter Lock) bedeutet, dass in einem Python-Programm zu jedem Zeitpunkt nur ein Thread ausgeführt werden kann. Das heißt, wenn wir einen Thread erstellen und ihn parallel ausführen möchten, geschieht dies nicht. Die eigentliche Aufgabe des Python-Interpreters besteht darin, schnell zwischen verschiedenen laufenden Threads zu wechseln. Aber das ist eine sehr einfache Erklärung dessen, was tatsächlich passiert, die viel komplexer ist. Es gibt viele Beispiele für die parallele Ausführung, beispielsweise die Verwendung verschiedener Bibliotheken, bei denen es sich im Wesentlichen um C-Erweiterungen handelt. Wenn Sie jedoch Python-Code ausführen, wird dieser meistens nicht parallel ausgeführt. Mit anderen Worten: Threads in Python sind nicht wie Threads in Java oder C.

Viele Leute werden versuchen, Python zu verteidigen, indem sie sagen, dass es sich um echte Threads handelt. Das ist sicherlich wahr, aber es ändert nichts an der Tatsache, dass Python Threads anders behandelt, als Sie erwarten. Die gleiche Situation besteht mit der Ruby-Sprache (Ruby verfügt auch über eine Interpretersperre).

Die angegebene Lösung besteht in der Verwendung des Multiprocessing-Moduls. Das Multiprocessing-Modul stellt die Process-Klasse bereit, die eine gute Überlagerung für Fork darstellt. Allerdings ist ein Fork-Prozess viel teurer als ein Thread, sodass Sie möglicherweise nicht jedes Mal eine Leistungsverbesserung feststellen, da zwischen verschiedenen Prozessen viel Arbeit geleistet werden muss, um sie miteinander zu koordinieren.

Dieses Problem besteht jedoch nicht in jeder Implementierung von Python. Beispielsweise versucht eine Implementierung von Python, PyPy-stm, die GIL loszuwerden (sie ist immer noch instabil). Python-Implementierungen, die auf anderen Plattformen wie JVM (Jython) oder CLR (IronPython) basieren, weisen ebenfalls keine GIL-Probleme auf.

Kurz gesagt, seien Sie vorsichtig, wenn Sie die Thread-Klasse verwenden, da das, was Sie erhalten, möglicherweise nicht das ist, was Sie wollen.

6. Verwenden Sie Klassen im alten Stil

在Python 2中,有两种类型的类,分别为“旧式”类和“新式”类。如果你使用Python 3,那么你默认使用“新式”类。为了确保在Python2中使用“新式”类,你需要让你新创建的每一个类都继承object类,且类不能已继承了内置类型,例如int或list。换句话说,你的基类、类如果不继承其他类,就总是需要继承object类。

class MyNewObject(object):
# stuff here

   

这些“新式”类解决一些老式类的根本缺陷,想要详细了解新式类和旧式类请参见《python新式类和旧式类区别》《python2中的__new__与__init__,新式类和经典类》。

7.按错误的方式迭代

对于这门语言的新手来说,下边的代码是非常常见的:

for name_index in range(len(names)):
print(names[name_index])

   

在上边的例子中,没有必须调用len函数,因为列表迭代实际上要简单得多:

for name in names:
print(name)

   

此外,还有一大堆其他的工具帮助你简化迭代。例如,可以使用zip同时遍历两个列表:

for cat, dog in zip(cats, dogs):
print(cat, dog)

如果你想同时考虑列表变量的索引和值,可以使用enumerate:

   
for index, cat in enumerate(cats):
print(cat, index)

在itertools中也有很多有用的函数供你选择。然而请注意,使用itertools函数并不总是正确的选择。如果itertools中的一个函数为你试图解决的问题提供了一个非常方便的解决办法,例如铺平一个列表或根据给定的列表创建一个其内容的排列,那就用它吧。但是不要仅仅因为你想要它而去适应你代码的一部分。

滥用itertools引发的问题出现的过于频繁,以至于在StackOverflow上一个德高望重的Python贡献者已经贡献他们资料的重要组成部分来解决这些问题。

8.使用可变的默认参数

我多次见到过如下的代码:

def foo(a, b, c=[]):
# append to c
# do some more stuff

永远不要使用可变的默认参数,可以使用如下的代码代替:

def foo(a, b, c=None):
if c is None:
c = []
# append to c
# do some more stuff

   

与其解释这个问题是什么,不如展示下使用可变默认参数的影响:

>>> def foo(a, b, c=[]):
... c.append(a)
... c.append(b)
... print(c)
...
>>> foo(1, 1)
[1, 1]
>>> foo(1, 1)
[1, 1, 1, 1]
>>> foo(1, 1)
[1, 1, 1, 1, 1, 1]

同一个变量c在函数调用的每一次都被反复引用。这可能有一些意想不到的后果。

总结

这些只是相对来说刚接触Python的人可能会遇到的一些问题。然而请注意,可能会遇到的问题远非就这么些。然而另一些缺陷是人们像使用Java或C++一样使用Python,并且试图按他们熟悉的方式使用Python。


Stellungnahme:
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