Python学習の---pythonパラメータタイプ注記
35394 ワード
pythonパラメータタイプ注記 Pythonは動的言語であり、変数は随時付与可能であり、異なるタイプの に付与可能である. Pythonは静的コンパイル言語ではなく、変数タイプは実行期間によって決定される である.ダイナミック言語は柔軟ですが、この特性も弊害 です.は発見しにくい:いかなるタイプの検査をしないため、運行期間の問題が現れるまで、あるいはオンライン運行時に問題を暴露することができる .使いにくい:関数の使用者が関数を見たとき、あなたの関数の設計を知らないで、どんなタイプのデータを伝えるべきか分からない このような動的言語定義の弊害をどのように解決するか. ドキュメントDocumentation Stringを追加 これは単なる慣例であり、強制基準ではなく、プログラマに関数の説明ドキュメント を提供するように要求することはできません.関数定義が更新され、ドキュメントが必ずしも同期更新されるとは限らない
関数注記 Python 3.5導入 関数のパラメータのタイプ注記 関数の戻り値のタイプ注記 は、関数パラメータのみを補助的に説明し、関数パラメータのタイプチェック は行わない.はサードパーティのツールに提供し、コード分析を行い、隠されたバグ を発見した.関数注記の情報はannotationsプロパティに 保存されます.
変数注記 Python 3.6導入.ただし、i:int=3 を強制しない変数の説明にすぎません.
ビジネスアプリケーション関数パラメータタイプチェック 考え方 関数パラメータの検査は、必ず関数の外にあり、検査コードを関数に侵入する である.関数はパラメータとして検査関数 に入力されるべきである.検査関数は、関数が入力した実際のパラメータを取得し、パラメータ宣言と比較して を取得する. **__annotations__**属性は、戻り値タイプの宣言を含む辞書です.位置パラメータの判断を行うには、辞書の宣言に対応できないと仮定します.i を使用
は、オブジェクト情報を取得する関数を提供し、関数およびクラス、タイプチェック を検査することができる.
inspectモジュール signature(callable)は、署名(関数署名は、関数名、そのパラメータタイプ、その存在するクラスおよび名前空間、およびその他の情報を含む関数の情報を含む) を取得する.
操作
説明
inspect.ismethod(add))
クラスのメソッドかどうか
inspect.isgenerator(add))
ジェネレータオブジェクトかどうか
inspect.isgeneratorfunction(add))
ジェネレータ関数かどうか
inspect.isclass(add))
クラスかどうか
inspect.ismodule(inspect))
モジュールかどうか
inspect.isbuiltin(print))
組み込みオブジェクトかどうか
inspect.isfunction(add)
関数かどうか Parameterオブジェクト はメタグループに保存され、読み取り専用の である. name、パラメータの名前 annotation、パラメータの注記、 が定義されていない可能性があります default、パラメータのデフォルト値、 が定義されていない可能性があります. empty、default属性または注釈annotation属性をマークするための特殊なクラス kind,実パラメータがどのようにパラメータにバインドされるかは,パラメータのタイプである. POSITIONAL_ONLY、値は位置パラメータ提供#pythonにposition_が存在しない必要がありますonly POSITIONAL_OR_KEYWORD、値はキーワードまたは位置パラメータとして を提供することができる. VAR_POSITIONAL、可変位置パラメータ、対応*args KEYWORD_ONLY,keyword-onlyパラメータ,args以降の出現に対応する非可変キーワードパラメータ VAR_KEYWORD,可変キーワードパラメータ,対応***kwargs*
例:には、次の の関数があります.
ユーザー入力がパラメータ注記の要件を満たしているかどうかを確認してください.
考え方:が呼び出すと、ユーザが入力実パラメータが要求 に合致するか否かを判断する.が呼び出されたとき、ユーザはadd関数 が呼び出されたと感じた.ユーザーが入力したデータと宣言のタイプを比較し、一致しない場合は ユーザーに提示する.
考える?ビジネス要件がパラメータに注釈がある場合、実パラメータタイプと宣言の一致が要求され、宣言がない場合は比較されます.どのように実現しますか?
パラメータ注記の使用は、関数の実行中の正確性を保証し、エラーが発生してシステムがクラッシュすることはありません.タイプに合わないパラメータがあれば、ログ、データベースなどにジャンプして、相応の修正を行うことができます.パラメータタイプの不一致による損失をよく解決した.
def add(x, y):
return x + y
print(add(4, 5))
print(add('hello', 'world'))
add(4, 'hello') #int ,
def add(x:int,y:int):# ,
"""
x:int
y:int
return:int
""" # ,
return x+y
変数注記
ビジネスアプリケーション
nspect
モジュールinspet
モジュールinspectモジュール
import inspect
inspect.isfunction(int)
inspect.signature(add)# , return
def add(x:int,y:int,*args,**kwargs)-->int:
return x+y
sig = inspect.signature(add)# , return
print(sig,type(sig))
>>>(x:int, y:int, *args, **kwargs) -> int <class 'inspect.Signature'>
# sig
sig.parameters
>>>mappingproxy({'x': <Parameter "x:int">,
'y': <Parameter "y:int">,
'args': <Parameter "*args">,
'kwargs': <Parameter "**kwargs">}) # ,
sig.return_annotation # , , inspect_empty
>>>int # inspect._empty
print(sig.parameters['y'], type(sig.parameters['y']))
>>> y:int <class 'inspect.Parameter'> # y int
print(sig.parameters['kwargs'],sig.parameters['kwargs'].annotation)
>>> **kwargs <class 'inspect._empty'> # y , , ,
操作
説明
inspect.ismethod(add))
クラスのメソッドかどうか
inspect.isgenerator(add))
ジェネレータオブジェクトかどうか
inspect.isgeneratorfunction(add))
ジェネレータ関数かどうか
inspect.isclass(add))
クラスかどうか
inspect.ismodule(inspect))
モジュールかどうか
inspect.isbuiltin(print))
組み込みオブジェクトかどうか
inspect.isfunction(add)
関数かどうか
inspect
関数もたくさんありますが、必要に応じてinspectモジュールのヘルプを参照してください.例:
import inspect
def add(x, y:int=7, *args, z, t=10,**kwargs) -> int:
return x + y
sig = inspect.signature(add) #
print(sig)
print('params : ', sig.parameters) # ('x', )
print('return : ', sig.return_annotation) # return , empty
print('~~~~~~~~~~~~~~~~')
for i, item in enumerate(sig.parameters.items()): #
name, param = item #
print(i+1, name, param.annotation, param.kind, param.default)# ,
print(param.default is param.empty, end='
') # param.empty
>>>
(x, y:int=7, *args, z, t=10, **kwargs) -> int
params : OrderedDict([('x', <Parameter "x">), ('y', <Parameter "y:int=7">), ('args', <Parameter "*args">), ('z', <Parameter "z">), ('t', <Parameter "t=10">), ('kwargs', <Parameter "**kwargs">)])
return : <class 'int'>
~~~~~~~~~~~~~~~~
1 x <class 'inspect._empty'> POSITIONAL_OR_KEYWORD <class 'inspect._empty'>
True
2 y <class 'int'> POSITIONAL_OR_KEYWORD 7
False
3 args <class 'inspect._empty'> VAR_POSITIONAL <class 'inspect._empty'>
True
4 z <class 'inspect._empty'> KEYWORD_ONLY <class 'inspect._empty'>
True
5 t <class 'inspect._empty'> KEYWORD_ONLY 10
False
6 kwargs <class 'inspect._empty'> VAR_KEYWORD <class 'inspect._empty'>
True
def add(x, y:int=7) -> int:
return x + y
ユーザー入力がパラメータ注記の要件を満たしているかどうかを確認してください.
考え方:
import inspect
def add(x, y:int=7) -> int:
return x + y
def check(fn): #d
def wrapper(*args, **kwargs):
sig = inspect.signature(fn)
params = sig.parameters
values = list(params.values()) # params value ,
for x,(k,v) in zip(args,params.items()): # zip ,
if not isinstance(x,v.annotation): #
raise Exception('wrong param= {}{}'.format(k, x))
# for i,p in enumerate(args):
# if isinstance(p, values[i].annotation): #
# print('==')
# , , key
for k,v in kwargs.items(): #
if isinstance(v, params[k].annotation): #
print('===')
return fn(*args, **kwargs)
return wrapper
check(add)(20,10)
check(add)(20,y=10)
check(add)(x=20,y=10)
考える?ビジネス要件がパラメータに注釈がある場合、実パラメータタイプと宣言の一致が要求され、宣言がない場合は比較されます.どのように実現しますか?
import inspect
from inspect import Parameter
def check (fn):
def wrapper (*args,**kwargs):
sig = inspect.signature(add)
params = sig.parameters
values = list(params.values())
keys = list(params.keys())
# for i ,x in enumerate(args): #print(check(add)(4,5))
# if not isinstance(x,values[i].annotation):
# raise Exception ('wrong param= {}{}'.format(keys[i],x))
flag =True
for x,(k,v) in zip(args,params.items()): # zip
if v.annotation != inspect._empty and not isinstance(x,v.annotation):
#
raise Exception('wrong param= {}{}'.format(k, x))
flag =False
for k,v in kwargs.items(): # print(check(add)(4,y=5))
if params[k].annotation != inspect._empty and not isinstance(v,params[k].annotation):
raise Exception('wrong param= {}{}'.format(k, v))
flag =False
if not flag: # ,
pass
return
else:
ret =fn(*args,**kwargs)#
return ret
return wrapper
@check # add = check(add)=> wrapper(4,5) #
def add(x :int ,y :int=7 )->int:
return x+ y
# print(check(add)(4,5))
# print(check(add)(4,y=5))
print(check(add)(x=4,y=5))
パラメータ注記の使用は、関数の実行中の正確性を保証し、エラーが発生してシステムがクラッシュすることはありません.タイプに合わないパラメータがあれば、ログ、データベースなどにジャンプして、相応の修正を行うことができます.パラメータタイプの不一致による損失をよく解決した.