Python如何檢查函數的參數信息?或者獲取參數的信息呢? __defaults__ 與__code__vs inspect - Python

Posted by: Max Chen | in Python | 1 year, 1 month ago |

為什麼需要檢查參數的型態?或者提取其詳細資訊?

讓我們先看下方Python Web框架,BoboGetting Started中的例子,說明這個機制被使用在哪裡:

這是一個bobo的官網的例子,我們將他改寫如下

import bobo

@bobo.query('/')
def hello(name):
    return "Hello %s!" % name

然後我們將他Run起來:

bobo -f hello.py

image

仔細觀察以下兩個結果,第一個結果產生403,第二個結果成功"Hello max!",原因在於第二個方法多傳了"?name=max"給bobo,而第一個方法並未傳給bobo。

curl -i http://localhost:8080/

image

curl -i http://localhost:8080/?name=max

image

也就是說,bobo明確的知道,hello函數是需要一個name參數的,但是bobo是利用什麼方法知道的?

沒錯,就是利用__defaults__ +__code__或inspect!


下面是一個範例函數(此函數為取得指定長度的字串,並移除最後空格,不過實際做什麼不是此處重點。)

def clip(text, max_len=80):
    """Return text clipped at the last space before or after max_len
    """
    end = None
    if len(text) > max_len:
        space_before = text.rfind(' ', 0, max_len)
        if space_before >= 0:
            end = space_before
        else:
            space_after = text.rfind(' ', max_len)
            if space_after >= 0:
                end = space_after
    if end is None:  # no spaces were found
        end = len(text)
    return text[:end].rstrip()

defaults__與__code

函數中有個 defaults 屬性,它是一個tuple,裡面保存著定位參數和關鍵字參數的默認值(僅限關鍵字參數的默認值在 kwdefaults 屬性中),而參數的名稱在 code 屬性中,它的值是一個 code 對象引用,自身也有很多屬性。

clip.__defaults__
clip.__code__ 
clip.__code__.co_varnames

image

  1. clip.defaults:得到了參數的值(80),但有個缺點,我們不知道這個值是對應哪個參數。
  2. clip.code :是個object的Reference。
  3. clip.code.co_varnames :給出了此函數用到的參數與變數。

依照以上的資訊,我們確實有一些方法可以推論出,參數是text/max_len,並且max_len的值預設為80,但顯得不那麼直覺,幸好,我們有inspect!

inspect

from inspect import signature 
sig = signature(clip)
sig
str(sig)
for name, param in sig.parameters.items(): 
    print(param.kind, ':', name, '=', param.default)

image

inspect._empty表示沒有預設值。

inspect.signature 函數返回一個 inspect.Signature Object,它有一個 parameters 屬性,這是一個有序映射,所以可以把參數名和 inspect.Parameter 一一對應起來,直覺許多了對吧~

那(bobo)框架又是怎麼實際的去判斷的呢?

inspect.bind

inspect.Signature 中有個 bind 方法,它可以把任意個參數綁定到簽名中的形參上,實參到形參所用的匹配規則需要一模一樣。框架正式使用這個方法在真正調用函數前驗證參數。

my_para = {'text':'123456 8 1','max_len':80}
bound_args = sig.bind(**my_para) #傳入參數正確!
my_para = {'max_len':80} 
bound_args = sig.bind(**my_para) #傳入參數錯誤!

image

其實這也與解釋器使用的機制相同,框架和 IDE 等工具可以使用這些信息驗證代碼!

以上就是本次內容,Python如何檢查函數的參數信息或獲取參數的信息,你學會了嗎?

Reference:

https://blog.louie.lu/2017/08/08/inspect-python-standard-library-11/

https://bobo.readthedocs.io/en/latest/

https://www.books.com.tw/products/0010706172

Current rating: 3
 or 

Subscribe

* indicates required

Recent Posts

Archive

2023
2022
2021

Categories

Apache 1

Data Science 2

Dbfit 1

Design Pattern 1

Devops 4

DigitalOcean 1

Django 1

English 3

Excel 5

FUN 4

Flask 3

Git 1

HackMD 1

Heroku 1

Html/Css 1

Linux 4

MDX 1

Machine Learning 2

Manufacture 1

Master Data Service 1

Mezzanine 18

Oracle 1

Postgresql 7

PowerBI 4

Powershell 4

Python 22

SEO 2

SQL Server 53

SQL Server Analytics Service 1

SQLite 1

Windows 1

database 8

work-experience 1

其他 1

投資入門 1

投資心得 2

時間管理 1

總體經濟 2

自我成長 3

資料工程 1

Tags

SEO(1) Github(2) Title Tag(2) ML(1) 李宏毅(1) SQL Server(18) Tempdb(1) SSMS(1) Windows(1) 自我成長(2) Excel(1) python Flask(1) python(5) Flask(2)

Authors

Max Chen (159)

Feeds

RSS / Atom

Python如何檢查函數的參數信息?或者獲取參數的信息呢? __defaults__ 與__code__vs inspect - Python

© COPYRIGHT 2011-2022. Max的文藝復興. ALL RIGHT RESERVED.