简体   繁体   English

如何以 python 方式处理具有相同操作的不同输入类型?

[英]How to handle different input types with the same actions pythonically?

I have written some code that allow both torch.Tensor and np.ndarray data types.我写了一些代码,允许torch.Tensornp.ndarray数据类型。

The functions will perform the same operations but since they are both different APIs for some code, I need to always do an isinstance check in order to perform the operation.这些函数将执行相同的操作,但由于它们是某些代码的不同 API,因此我需要始终执行isinstance检查才能执行操作。

An example:一个例子:

import torch
import numpy as np
from typing import Union

torch_tensor = torch.tensor([1, 2, 3])
numpy_array = np.array([1, 2, 3])


def expand(inputs: Union[torch.Tensor, np.ndarray]) -> Union[torch.Tensor, np.ndarray]:
    if isinstance(inputs, torch.Tensor):
        return inputs.unsqueeze(0)
    elif isinstance(inputs, np.ndarray):
        return np.expand_dims(inputs, 0)
    else:
        raise TypeError("inputs must be either a torch.Tensor or a numpy.ndarray")

One or two functions with this kind of isinstance check is fine, but it is not very "neat" when I add in more functions with the same kind of interface as expand .使用这种isinstance检查的一个或两个函数很好,但是当我添加更多具有与expand相同类型接口的函数时,它不是很“整洁”。 Any tips or design that could handle this more elegantly, so that I do not need to perform the isinstance checks in every function.任何可以更优雅地处理这个问题的技巧或设计,这样我就不需要在每个 function 中执行isinstance检查。

Expanding on my comment, instead of扩展我的评论,而不是

from typing import Union
import random

def add_to_a(value: Union[int, str]) -> Union[int, str]:
    if isinstance(value, int):
        return value + 1
    elif isinstance(value, str):
        return str(int(value) + 1)

a = random.choice([0, "0"])

print(add_to_a(a))

I would structure the code to something alike this, where each type has a separate pipeline starting from the top level when the variable enters.我会将代码构造成类似这样的结构,其中当变量进入时,每种类型都有一个从顶层开始的单独管道。

import random

def add_to_int_a(value: int) -> int:
    return value + 1

def add_to_str_a(value: str) -> str:
    return str(int(value) + 1)

a = random.choice([0, "0"])

if isinstance(a, int):
    print(add_to_int_a(a))
    # Other int type processing
elif isinstance(a, str):
    print(add_to_str_a(a))
    # Other str type processing

This is the case mostly if there are going to be more of these "Union" functions in the processing pipeline.如果处理管道中将有更多这些“联合”功能,则大多数情况下都是这种情况。 For one Union here and other there it doesn't really matter personally.对于这里的一个联盟和那里的另一个联盟来说,这对个人来说并不重要。

This comes down to DRY (Don't repeat yourself) with the abundance of isinstance checks in the processing functions if we're following the first example with every operation.如果我们在每个操作中都遵循第一个示例,这归结为DRY(不要重复自己)处理函数中的大量isinstance检查。

Also worth noting, it could be worthwile to construct classes to help differentiate and group the functionalities if it helps the readability at all.同样值得注意的是,构建类来帮助区分和分组功能可能是值得的,如果它有助于提高可读性的话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM