[英]Python Generic functions with generic parameters
我不確定我是否在標題中使用了正確的術語。 這可能是為子系統或模塊編寫接口函數的一種已知方法,但因為我不知道關鍵字,所以我在搜索查詢中找不到結果。
我想創建一個function,其意圖可以在函數名稱中清楚地描述,但參數是靈活的。 我想編寫 function 足夠通用,以便 function 可以使用它從任何調用者接收到的任何參數來完成意圖。
讓我們以 function do_foo
。 do_foo
可以接受some_obj
,其屬性允許do_foo
完成其工作。 此外, do_foo
可以只接收它關心的單個屬性,如obj_attr0
或obj_attr1
並執行相同的工作。 在這兩種情況下,預期的結果也是相同的。
所以這看起來像這樣:
Class SomeObj():
def __init__(self, obj_attr0, obj_attr1, obj_attrN):
self.obj_attr0 = None
self.obj_attr1 = None
self.obj_attrN = None # denotes an N number of attributes
def do_foo(params)
# unpack params. do_foo requires obj_attr0 and obj_attr1 and so its searching it in the params iterable
# determine which data is passed in
# execute the work the same way regardless of what form the data is passed in
pass
obj_attr0 = None
obj_attr1 = None
obj_attrN = None
some_obj = SomeObj(obj_attr0, obj_attr1, obj_attrN)
# One can either call with a subset of attributes that would make up SomeObj or SomeObj itself if all the information is there. E.g.:
params = (some_obj)
do_foo(params)
# OR
params = (obj_att0, obj_attr1)
do_foo(params)
我知道 python 提供 *args 和 **kwargs 設施,提供上述靈活性。 我正在尋找一些例子來說明實施有助於減少陷阱的地方。 實現上述內容的好方法是什么? 如果那里有任何資源,那么描述上述編程風格的示例/文章/或術語是什么? 顯然,我正在嘗試將我的接口函數編寫為通用且可在多個邏輯路徑中使用,其中用戶將其數據存儲在不同的 forms 中,其中堅持特定的參數列表會受到限制。
您可以使用 function 裝飾器來執行此操作
我有一個具體的例子給你。 它可能不是最漂亮的代碼,但它的功能類似於您所要求的。
I made a mini HTTP testing library because I make my REST http tests in python, and I realized that I always write the same code again and again. 所以我做了一個更一般的設置
核心有點丑,這是我不想一次又一次地寫的部分。
只需快速跳過這部分並檢查它在接口部分的使用方式。
然后,如果您喜歡它,您可以返回 go 並嘗試了解它們是如何聯系在一起的。
# base.py
import json, requests, inspect
# This function drops invallid parameters
def request(*args, **kwargs):
allowed = inspect.signature(requests.Session.request).parameters
return {k:v for (k,v) in kwargs.items() if k in allowed}
def response(r, code):
if r.status_code != code:
print(r.text)
return
data = r.json()
if data:
print(json.dumps(data, indent=2, ensure_ascii=False))
return data
# This is the core function it is not pretty but it creates all the abstaction in multiple levels of decorations.
def HTTP(base_url):
def outer(func_one):
def over(*args_one, **kwargs_one):
req, url, code = func_one(*args_one, **kwargs_one)
url = base_url + url
def inner(func_two):
def under(*args_two, **kwargs_two):
allowed = inspect.signature(func_two).parameters
kwparams = {k:v for (k,v) in kwargs_two.items() if k in allowed}
from_inner = func_two(*args_two, **kwparams)
u = url.format(id=kwargs_two.pop('_id')) if '{id}' in url else url
r = req(u, **request(**kwargs_two, **from_inner))
return response(r, code)
return under
return inner
return over
return outer
The interface functions are all each decorated by the HTTP
function which makes them a HTTP caller function, it is still abstract since it will return a function.
注意:接口就是我所說的,但它實際上只是返回基於 HTTP 裝飾器的函數的函數
BASE_URL = "https://example.com"
@HTTP(BASE_URL)
def POST(url, code=200): return requests.post, url, code
@HTTP(BASE_URL)
def PUT(url, code=200): return requests.put, url, code
@HTTP(BASE_URL)
def DELETE(url, code=200): return requests.delete, url, code
@HTTP(BASE_URL)
def GET(url, code=200): return requests.get, url, code
當其中一個接口函數用這個修飾時,它們需要一個令牌。
def AUTH(func):
def inner(token, *args, **kwargs):
headers = {'Authorization': f'bearer {token}'}
return func(*args, **kwargs, headers=headers)
return inner
該接口可用於許多實現。
這里我使用用戶 model 的 POST、PUT、GET 和 DELETE 接口。
這是最后的裝飾,返回的函數實際上將返回內容而不是其他函數。
# users.py
from httplib.base import (
POST,
GET,
DELETE,
PUT,
AUTH,
request
)
@POST('/users',200)
def insert(user):
return request(json=user)
@AUTH
@GET('/users')
def find(_filter={}):
return request(params=_filter)
@AUTH
@GET('/users/{id}')
def find_one(_id):
return request()
@AUTH
@DELETE('/users/{id}')
def delete(_id):
return request()
@AUTH
@PUT('/users/{id}')
def update(_id, updates={}):
return request(json=updates)
在這里,您可以看到用戶刪除插入和查找功能是如何工作的。
from httplib import users
def create_and_delete_users(token, n): return [
users.delete(token, _id=x['user']['id'])
for x in [
users.insert(user={
'username' : f'useruser{str(i).zfill(2)}',
'password' : 'secretpassword',
'email' : f'useruser{str(i).zfill(2)}@mail.com',
'gender' : 'male',
}) for i in range(n)]
]
def find_all_and_then_find_each(token): return [
users.find_one(token, _id=x['id'])
for x in users.find(token)['data']
]
我希望這可以幫到你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.