在Python中,我希望有一个函数可以处理不同的输入类型。像这样:
def my_square(x):
return x ** 2
my_square(2) #return 4
my_square(range(10)) #should return a list [0 ... 81]
npa = numpy.zeros(10)
my_square(npa) # should return a numpy array with the squares of zeros
基本上,为标量和可迭代编写函数的好习惯是什么?这可以用* args或* kwargs来完成吗?
答案 0 :(得分:0)
执行此操作的典型方法是使用numpy.asarray
将您的函数输入转换为ndarray
。如果输入是标量,则结果是具有0维的数组,其行为基本上类似于Python数字类型。例如:
def square(x):
x = np.asarray(x)
return x**2
那样:
>>> square(4)
16
>>> square([1, 2, 3, 4])
array([ 1, 4, 9, 16])
请注意,我将列表作为输入并收到ndarray
作为输出。如果绝对必须接收与输入相同类型的输出,您可以在返回之前转换结果:
def square(x):
in_type = type(x)
x = np.asarray(x)
return in_type(x**2)
但这会带来额外的成本,但收效甚微。
答案 1 :(得分:0)
由于Python是动态类型的,并且Python的设计理念违背了在调用函数时希望区别显而易见的想法,因此不会将其视为 Pythonic 。但是,如果必须的话,您可以使用isInstance()
方法来完成您想要的任务。例如:
def mySquare(x):
if isinstance(x, int):
return x**2
elif isinstance(x, range):
return [i ** 2 for i in x]
print(mySquare(2)); //4
print(mySquare(range(10))); //[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
然而,仅仅因为你可以做某事,并不意味着你应该做。
Refer to this question for further information on isinstance,我建议您同时查看Duck Typing。
此外,single dispatch function也可能提供您所需要的内容,但我没有足够的经验为此提供解释,但是,这可能是您想要查看的内容。
答案 2 :(得分:0)
这样做会更好,而且更容易维护:
def foo(n):
return n ** 2
然后在需要时构建列表,dicts等(我不是很熟悉numpy
,但我想你可以做类似的事情):
foo_list = [foo(n) for n in range(10)]
foo_dict = {n: foo(n) for n in range(10)}
似乎有numpy
使用numpy.fromiter()。来自文档:
iterable = (foo(n) for n in range(5))
foo_arr = np.fromiter(iterable, np.whatever_numpy_datatype)
如果你真的需要,你甚至可以将它们变成功能:
def foo_list(start=0, stop=0):
return [foo(n) for n in range(start, stop)]
def foo_dict(start=0, stop=0):
return {n: foo(n) for n in range(10)}
另一个选择是,要求宽恕比获得更容易:
def foo(scalar_or_iter):
try:
return [n ** 2 for n in scalar_or_iter]
except TypeError:
return scalar_or_iter ** 2
答案 3 :(得分:0)
正如评论中所建议的,只需编写函数的标量版本,并使用map for lists etc和imap for iterables(map不适用于那些):
map(myFunc,myList)
和
import itertools
itertools.imap(myFunc,myIterable)