この章では、Fernando Doglio によって書かれた「Python Performance Analysis and Optimization」の知識体系を引き続き使用し、主に最適化の詳細に基づいて、独自の実用的なアプリケーションと組み合わせます.ctypes の使用に焦点を当てています.
記事ディレクトリ
関数戻り値キャッシュ/関数参照テーブル
デフォルトパラメータの使用
既定のパラメーター (既定の引数) は、実行時に入力を決定するのではなく、関数の作成時に入力値を決定できます。
ここで Python パラメーターを確認します。
-
位置引数
-
キーワード引数
def trapezoid_area(base_up, base_down, height) return 1/2 * (base_up + base_down) * height trapezoid_area(1, 2, 3) # 位置参数 trapezoid_area(base_up=1, base_down=2, height=3) # 关键词参数 trapezoid_area(height=3, base_down=2, base_up=1) # right trapezoid_area(height=1, base_down=2, 1) # wrong trapezoid_area(base_up=1, base_down=2, 3) # right trapezoid_area(1, 2, height=3)
-
デフォルトのパラメータ
デフォルトパラメータ=デフォルト値、関数が呼び出されたとき、デフォルトパラメータの値が渡されない場合、デフォルト値と見なされます。
デフォルト パラメータは、位置パラメータの後に。そうしないと、プログラムがエラーを報告します。
def trapezoid_area(base_up, base_down, height=3) return 1/2 * (base_up + base_down) * height trapezoid_area(1, 2) trapezoid_area(1, 2, height=3) # 位置参数
-
可変引数
可変パラメーターとは、渡されるパラメーターの数が可変であり、0、1、2 の任意の数であり、可変長パラメーターであることを意味します。
def printinfo(arg1, *args): # *args - 可变参数,可以是从零个到任意个,自动组装成元组。 print('arg1:' + str(arg1)) print('args:', end=' ') for var in args: print(var, end=' ') print(' ') printinfo(10) # 10 printinfo(70, 60, 50)
プログラムを実行した結果は次のとおりです。
arg1:10 args: arg1:70 args: 60 50 Process finished with exit code 0
-
キーワード引数
def printinfo(arg1, *args, **kwargs): # **kwargs - 关键字参数,可以是从零个到任意个,自动组装成字典。 print(arg1) print(args) print(kwargs) printinfo(70, 60, 50) # 70 # (60, 50) # {} printinfo(70, 60, 50, a=1, b=2) # 70 # (60, 50) # {'a': 1, 'b': 2}
プログラム中のコメント部分が実行結果です。
-
名前付きキーワード引数 (name キーワード引数)
*, nkw
- nkw の前にセパレーターを追加することによって定義される、ユーザーが入力したいキーワード・パラメーターである名前付きキーワード・パラメーター*
。- キーワード パラメータの名前を制限する場合は、「名前付きキーワード パラメータ」を使用できます。
- 名前付きキーワード パラメータを使用する場合は、パラメータ名が欠落していないことに特に注意してください。
def printinfo(arg1, *, nkw, **kwargs): print(arg1) print(nkw) print(kwargs) printinfo(70, nkw=10, a=1, b=2) # 70 # 10 # {'a': 1, 'b': 2} printinfo(70, 10, a=1, b=2) # TypeError: printinfo() takes 1 positional argument but 2 were given
-
パラメータの組み合わせ
To define a function in Python, you can use positional parameters, default parameters, variable parameters, named keyword parameters, and keyword parameters. これら 5 種類のパラメーターのうち 4 つは一緒に使用できますが、パラメーター定義の順序は次のようにする必要があることに注意してください。
- 位置引数、デフォルト引数、可変個引数、およびキーワード引数。
- 位置引数、デフォルト引数、名前付きキーワード引数、およびキーワード引数。
可変長引数とキーワード引数を定義するための構文に注意してください。
*args
args
これは可変パラメータであり、tuple
**kwargs
kw
を受け取るキーワード引数です。dict
名前付きキーワード パラメータは、デフォルト値を提供しながら、呼び出し元が渡すことができるパラメータ名を制限するために使用されます。名前付きキーワード parameter を定義するときは、区切り文字を忘れずに記述してください
*
。そうしないと、定義は位置パラメーターになります。警告: 最大 5 つの引数を組み合わせることができますが、同時に多くの組み合わせを使用しないでください。関数が混乱する可能性があります。
リスト合成式ビルダー
プログラム計算の前に初期化などの操作を配置し、for ループをリスト合成式に置き換えます。
final_state_list = [FinalStatus() for x in range(opt.multiple_camera_number)]
ctypes
ctypes ライブラリを使用すると、開発者は Python の最下層に直接アクセスし、C 言語の力で開発できます。このライブラリは、このバージョンが C 言語で記述されているため、正式バージョンのインタープリター (CPython) でのみ使用できます。PyPy や Jython などの他のバージョンは、このライブラリにアクセスできません。
この時点で、キー コードを C 言語で記述し、ライブラリにコンパイルしてから、モジュールとして Python にインポートできます。
どの python インタープリターかを判断する方法元のテキストのコードを変更しました。自分の python 環境で cv を実行して、どのインタープリターが使用されているかを確認するだけです。
import sys
import os
try:
from platform import python_implementation
except ImportError: # pragma: no cover
def python_implementation():
"""Return a string identifying the Python implementation."""
if 'PyPy' in sys.version:
print('PyPy')
if os.name == 'java':
print('Jython')
if sys.version.startswith('IronPython'):
print('IronPython')
finally:
print('CPython')
ctypes の使用
ctypesの使い方について、いくつかの記事を読んで少し複雑に感じました.個人的には、ctypesの使い方は、純粋なcコードを外部リンクライブラリにコンパイルし、この外部リンクライブラリを使用するパイソン。
最初のステップ: 最初に ctypes_test.c を作成します
// 这是找素数的程序
#include <stdio.h>
#include <math.h>
int check_prime(int a)
{
int c;
for ( c = 2 ; c <= sqrt(a) ; c++ ) {
if ( a%c == 0 )
return 0;
}
return 1;
}
ステップ 2 : ファイルをコンパイルする
$ gcc -shared -o ct.so -fPIC .\ctypes_test.c
私の環境はanacondaにあり、gccがインストールされていますgcc version 8.1.0 (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project)
.gccのパラメータに関するいくつかの補足:
パラメータ | 関数 |
---|---|
-共有 | このオプションは動的ライブラリの使用を禁止するため、コンパイルされたものは一般に非常に大きく、動的リンク ライブラリなしで実行できます。 |
-静的 | このオプションはダイナミック ライブラリを使用しようとするため、生成されるファイルは比較的小さくなりますが、システムにはダイナミック ライブラリが必要です。 |
-fPIC | それはダイナミック リンク ライブラリですか。 |
ステップ 3 : 生成されたライブラリを python プログラムで呼び出す
import time
import ctypes
import math
# ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)
check_primes_types = ctypes.CDLL('./ct.so').check_prime # ctypes.CDLL('路径').函数名
def check_prime(x):
values = range(2, int(math.sqrt(x)))
for i in values:
if x % i == 0:
return False
return True
init = time.time()
numbers_py = [x for x in range(1000000) if check_prime(x)]
print("Full python version: %s seconds" % (time.time() - init))
init = time.time()
numbers_c = [x for x in range(1000000) if check_primes_types(x)]
print("C version: %s seconds" % (time.time() - init))
print(len(numbers_py))
予防
戻り値:ctypesがdllを呼び出す際の引数の型と戻り値の型について
パラメータ: python は c/c++ コードを呼び出して解決します ctypes.ArgumentError: 引数 1: クラス 'TypeError': 変換方法がわかりません
パラメータは配列です: ctypes の使用 (numpy 配列を c に渡す)
文字列連結
文字列は不変であるため、文字列の内容を変更するために何かを行うと、実際には新しい内容で新しい文字列が作成され、変数は新しく作成された文字列を指します。
リスト内の文字列を結合する
full_doc = ""
for word in word_list:
full_doc += word
と書き直した
full_doc = "".join(world_list)
可変補間
document = "%s%s%s%s" % (title, introduction, main_piece, conclusion)
その他の Python 最適化のヒント
不要なプログラムを削除する
# 173行
imc = im0.copy() if opt.save_crop else im0 # for save_crop