python oops Python函式註解

2021-10-21 02:57:01 字數 3830 閱讀 3024

以下內容基於python 3x

涉及的知識前提:

建議理解python裝飾器後學習此內容

函式註解概述

函式註解可以針對函式的引數、返回值新增元資料,其為註解。

python是動態語言,變數賦值時不會強制宣告型別,且能隨時重新賦值。無法像靜態編譯型語言一樣,在編譯時發現基本問題。

函式的引數要求,沒有詳細的doc string或更新沒跟上,以至後續的使用者不能夠清晰明白設計者要求的引數型別。以上行為導致的出錯率變高,難以使用等問題。

函式註解可以對引數的要求型別進行註解,對函式返回值進行註解;其只是對做乙個輔助性的說明,並不強制進行型別檢查。

一些第三方工具(pycharm)會對已定義的函式註解進行檢查標記提示等,在編寫**時同樣也可以通過編寫乙個裝飾器,來進行一些檢查。

實際應用

inspect模組

註解資訊儲存在函式的__annotations__屬性中,函式的引數檢查,一定是在函式實際執行之前,檢查傳遞進來的形參與原有的註解型別是否匹配。

__annotations__屬性是乙個字典,對於位置引數的判斷,較為複雜,可直接使用inspect模組獲取函式簽名資訊。

# 註解x和y引數要求為int型別,返回結果為int型別

# syntax:

def foo(x: int, y: int) -> int:

return x + y

檢視其__annotations__屬性資訊:

def foo(x: int, y: int) -> int:

return x + y

print(type(foo.__annotations__))

print(foo.__annotations__)

# 輸出結果:

使用inspect模組獲取簽名資訊:

inspect.signature返回的是乙個ordereddict(有序字典)

import inspect

def foo(x: int, y: int) -> int:

return x + y

sig = inspect.signature(foo)

print(sig.parameters)

# 輸出結果:

ordereddict([('x', ), ('y', )])

使用parameter方法,獲取更詳細的資訊:

import inspect

def foo(x: int , y: int, z=20) -> int:

return x + y + z

sig = inspect.signature(foo)

par = sig.parameters

print(par.items())

print(par["x"].name, "|-|", par["x"].annotation, "|-|", par["x"].default, "|-|", par["x"].empty, "|-|", par["x"].kind)

print(par["y"].name, "|-|", par["y"].annotation, "|-|", par["y"].default, "|-|", par["y"].empty, "|-|", par["y"].kind)

print(par["z"].name, "|-|", par["z"].annotation, "|-|", par["z"].default, "|-|", par["z"].empty, "|-|", par["z"].kind)

#輸出結果:

odict_items([('x', ), ('y', ), ('z', )])

x |-| |-| |-| |-| positional_or_keyword

y |-| |-| |-| |-| positional_or_keyword

z |-| |-| 20 |-| |-| positional_or_keyword

parameter輸出結果的資訊儲存在元組中,唯讀;

name:獲取引數名字;

annotation:獲取引數的註解,有可能沒有定義,則為_empty;

default:返回引數的預設值,如其中z引數的20即為預設值;

empty:特殊的類,用來標記default屬性或者注釋annotation屬性的空值;

kind:實參如何繫結到形參。以下是形參的型別:

positional_only,值必須是位置引數提供的(python中並沒有絕對的位置引數,未實現)。

positional_or_keyword,值可以作為關鍵字或者未知引數提供。

var_positional,可變位置引數,對應*args。

keyword_only,keyword-only引數,對應*args之後出現的非可變關鍵字引數。

var_keyword,可變關鍵字引數,對應**kwargs。

業務**

了解以上方法後,編寫乙個函式裝飾器用來檢測傳參是否規範。

首先在函式執行之前,獲取到函式簽名、及簽名的parameter資訊將parameter資訊。

kv結構的value轉換為列表儲存。

使用for迴圈檢查每個對應的parameter內引數(實際傳的引數)註解是否不為空並且同時是否不是已知型別(isinstance函式可以檢查傳的值是否是已知型別,返回true或false,簽名中引數的annotation型別為已知的)。

匹配通過,則說明傳遞的引數和註解要求型別一致,否則則丟擲typeerror型別的自定義錯誤資訊。

import inspect

import functools

def parameter_check(fn):

@functools.wraps(fn)

sig = inspect.signature(fn)

parameter = sig.parameters

value = list(parameter.values())

for i, par in enumerate(args):

if value[i].annotation is not value[i].empty and not isinstance(par, value[i].annotation):

raise typeerror("parameter type error")

for k, v in kwargs.items():

if parameter[k].annotation is not parameter[k].empty and not isinstance(v, parameter[k].annotation):

raise typeerror("parameter type error")

ret = fn(*args, **kwargs)

return ret

@parameter_check

def foo(x: int, y: int, z=20) -> int:

return x + y + z

print(foo(1, 50, 29))

# 輸出結果:

# 更改傳參,檢視效果:

print(foo("hhh", 50, 29))

# 輸出結果:

traceback (most recent call last):

file "e:/project/python/test.py", line 29, in

print(foo("hhh", 50, 29))

raise typeerror("parameter type error")

typeerror: parameter type error

總結通過對函式註解的了解,能夠更加規範**,提高效率,避免出錯。在實際應用中亦可方便的展開使用。

函式報錯注入 盲注

即利用系統輸出的報錯資訊來進行注入 floor報錯注入 floor報錯注入應該是報錯注入中最為複雜的一種了 其中的基礎為下面這句話 1select count floor rand 0 2 x from security.users group by x 需要注意的時候floor後面的x為乙個別名,...

連續函式註記

這是我在兩年前寫的一點東西,現在稍微整理一下,刪去了錯誤的內容,貼到這裡.乙個函式在某一點處連續的定義是 lim f x f a 這條式子說的是 對於任意給定的 varepsilon 0 都存在 delta 0 使得 x a delta 時都有 f x f a varepsilon 函式在某一點處連...

連續函式註記

這是我在兩年前寫的一點東西,現在稍微整理一下,刪去了錯誤的內容,貼到這裡.乙個函式在某一點處連續的定義是 lim f x f a 這條式子說的是 對於任意給定的 varepsilon 0 都存在 delta 0 使得 x a delta 時都有 f x f a varepsilon 函式在某一點處連...