簡體   English   中英

Python 具有泛型參數的泛型函數

[英]Python Generic functions with generic parameters

我不確定我是否在標題中使用了正確的術語。 這可能是為子系統或模塊編寫接口函數的一種已知方法,但因為我不知道關鍵字,所以我在搜索查詢中找不到結果。

我想創建一個function,其意圖可以在函數名稱中清楚地描述,但參數是靈活的。 我想編寫 function 足夠通用,以便 function 可以使用它從任何調用者接收到的任何參數來完成意圖。

讓我們以 function do_foo do_foo可以接受some_obj ,其屬性允許do_foo完成其工作。 此外, do_foo可以只接收它關心的單個屬性,如obj_attr0obj_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 裝飾器來執行此操作

長答案:

我有一個具體的例子給你。 它可能不是最漂亮的代碼,但它的功能類似於您所要求的。

迷你 HTTP 測試庫

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

一個中間件 function

當其中一個接口函數用這個修飾時,它們需要一個令牌。

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']
]

我希望這可以幫到你。

Python 錯誤“通用類型的參數必須是類型。得到<module "< div><div id="text_translate"><p> 當嘗試使用我自己的 class 作為類型提示時:</p><pre> from mycode.ltm import MyClass def DoSomething(self, values: List[MyClass]) -> None:</pre><p> 我得到:</p><blockquote><p> 泛型類型的參數必須是類型。 從“...”中獲取 <模塊“...”>。</p></blockquote><p> 如何解決這個問題?</p></div></module>

[英]Python error "Parameters to generic types must be types. Got <module "

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM