ホームページ  >  記事  >  バックエンド開発  >  Python での高度なプログラミングに関するいくつかのヒントのまとめ

Python での高度なプログラミングに関するいくつかのヒントのまとめ

伊谢尔伦
伊谢尔伦オリジナル
2017-06-28 13:29:401419ブラウズ

この記事では主に、講師やデコレータなどの重要な高度な知識ポイントを含む、Python の高度な プログラミング スキルを紹介します。これらはすべて、Python 開発を深く学ぶために必要な基本スキルです

。テキスト:

この記事では、高度な Python 設計構造とその使用方法を示します。日々の業務では、高速な検索性の要件、データの一貫性の要件、インデックスの要件など、ニーズに応じて適切なデータ構造を選択できます。また、さまざまなデータ構造を適切に組み合わせて、論理的なデータ構造を生成することもできます。わかりやすいデータモデル。 Python のデータ構造は構文的に非常に直感的であり、多数のオプションの操作を提供します。このガイドでは、一般的に使用されるデータ構造に関する知識のほとんどをまとめ、その最適な使用方法について説明します。
内包表記

Python を長期間使用している場合は、少なくともリスト内包表記について聞いたことがあるはずです。これは、for ループ、if、代入ステートメントを 1 つのステートメントにまとめる方法です。つまり、式を使用してリストをマップまたはフィルターできます。

リスト内包表記には次の部分が含まれます:

  • 入力シーケンス

  • 入力シーケンスのメンバーを表す変数

  • オプションのアサーション式

  • 入力シーケンス 条件を満たすメンバーアサーション式は、出力リスト メンバーの出力式に変換されます

たとえば、0 より大きいすべての整数を二乗することによって、入力リストから新しいシーケンスを生成する必要があります。次のように書くことができます:

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]

それは簡単です、右?しかし、これは 4 行のコード、2 レベルのネスト、そして完全に不必要な追加操作になります。フィルター関数、ラムダ関数、マップ関数を使用すると、コードを大幅に簡素化できます:

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]

このようにして、コードは水平方向に拡張されます。では、このままコードを単純化してもよいでしょうか?リスト導出によって答えが得られます:

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]
  • 反復子は入力シーケンスの各メンバーを走査します。 num は出力式に与えられ、二乗された後、出力リストのメンバーになります。

  • リスト内包表記はリストにカプセル化されているため、明らかに新しいリストを即座に生成できます。型関数の呼び出しのみがあり、ラムダ関数への暗黙的な呼び出しはありません。リスト内包表記では、通常の反復子、式、および if 式を使用してオプションのパラメーターを制御します。

  • その一方で、リストの内包にはいくつかの悪影響もある可能性があります。つまり、リスト全体を一度にメモリにロードする必要があります。これは、上記の例では問題になりません。また、その後でも問題はありません。何度か拡張されます。ただし、常に制限に達し、メモリは常に使い果たされます。
  • 上記の問題を考慮すると、

    Generator
  • (ジェネレーター)はそれを非常にうまく解決できます。ジェネレーター式はリスト全体を一度にメモリーにロードするのではなく、ジェネレーター
オブジェクト

(Generator objector) を生成するため、一度に 1 つのリスト要素のみがロードされます。

ジェネレーター式はリスト内包表記とほぼ同じ文法構造を持っています。違いは、ジェネレーター式が角かっこではなく括弧で囲まれていることです。

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
これは、コードの変更 1 に戻りましょう。特別な理由がない限り、コードでは常にジェネレーター式を使用する必要があります。ただし、非常に大きなリストを扱っている場合を除き、大きな違いは見られません。 次の例では、zip() 関数を使用して、2 つ以上のリスト内の要素を一度に処理します:

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]

2 段階のリスト内包表記を通してディレクトリ

を走査する例を見てみましょう:

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

デコレーター (デコレーター)



デコレーターは、既存の関数またはクラスの機能を強化する効果的な方法を提供します。それは Java のアスペクト指向プログラミング (アスペクト指向プログラミング) の概念によく似ていますか?どちらもシンプルですが、デコレーターの方が強力です。たとえば、関数の入口点と出口点で特別な操作 (セキュリティ、追跡、ロックなど) を実行したい場合は、デコレータを使用できます。

デコレータは、別の関数をラップする特別な関数です。メイン関数が呼び出され、その戻り値がデコレータに渡され、デコレータはメイン関数と残りの関数をラップする置換関数を返します。プログラム 表示される内容の一部は、このラッパー関数です。

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

構文シュガー @ はデコレータを識別します。

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

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)

当你写下如下代码时:
 

@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()

以上がPython での高度なプログラミングに関するいくつかのヒントのまとめの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。