Python 如何正确编写作用于列表的函数?
在Python中,我希望有一个处理不同输入类型的函数。大概是这样的:Python 如何正确编写作用于列表的函数?,python,list,Python,List,在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 th
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实现吗?实现这一点的典型方法是使用
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)
但是这样做会带来额外的成本,但好处不大。一种典型的方法是使用
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)
但这只会带来额外的成本,几乎没有什么好处。因为Python是动态类型的,而且Python的设计理念反对在调用函数时让差异变得明显的想法,所以这不被认为是Pythonic的。但是,如果必须的话,您可以使用该方法来实现您想要的。例如:
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]
然而,仅仅因为你能做某事,并不意味着你就应该做。
,我建议你也去看看
此外,a也可能提供您所需的内容,但我没有足够的经验来解释这一点,但是,这可能是您需要研究的内容。因为Python是动态类型的,Python的设计理念反对在调用函数时希望差异明显的想法,这不算是蟒蛇。但是,如果必须的话,您可以使用该方法来实现您想要的。例如:
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]
然而,仅仅因为你能做某事,并不意味着你就应该做。
,我建议你也去看看
此外,a也可能提供您所需的,但我没有足够的经验来解释这一点,但是,这可能是您需要研究的内容。只需执行以下操作,将是更好的实践,也更易于维护:
def foo(n):
return n ** 2
然后在需要时构建列表、dict等(我不太熟悉numpy
,但我想你也可以做类似的事情):
而且似乎有fornumpy
使用。从文档中:
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
只需执行以下操作就可以更好地实践和维护:
def foo(n):
return n ** 2
然后在需要时构建列表、dict等(我不太熟悉numpy
,但我想你也可以做类似的事情):
而且似乎有fornumpy
使用。从文档中:
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
正如注释中所建议的,只需编写一个标量版本的函数,并对列表等使用map,对iterables使用imap(map对这些函数不起作用): 及
正如注释中所建议的,只需编写一个标量版本的函数,并对列表等使用map,对iterables使用imap(map对这些函数不起作用): 及
为什么不编写只在标量上工作的函数呢?例如,
map
it-to-iterables?你当然可以在函数中处理这两个问题,但我会尽量避免。做你想做的事情是个坏主意,除非是在边缘情况下。为每种类型的输入编写版本。@jonrsharpe Numpy数组的设计目的是,无论其中使用的变量是标量还是数组,都可以编写有效的表达式。无论是x=4
还是x
是一个包含一百万个条目的ndarray
,OP的my_square(x)
都同样有效。在这种情况下,编写一个接受标量或iterable的函数是许多科学软件包中使用的一种常见的数值python习语,而使用map
将其应用于iterable显然是一种反模式。但是如果函数是通用的(并且不能利用numpy的矢量化),那么列表comp。或者地图是去的路。@jme很有趣,谢谢!为什么不编写只在标量上工作的函数呢?例如,map
it-to-iterables?你当然可以在函数中处理这两个问题,但我会尽量避免。做你想做的事情是个坏主意,除非是在边缘情况下。为每种类型的输入编写版本。@jonrsharpe Numpy数组的设计目的是,无论其中使用的变量是标量还是数组,都可以编写有效的表达式。无论是x=4
还是x
是一个包含一百万个条目的ndarray
,OP的my_square(x)
都同样有效。在这种情况下,编写一个接受标量或iterable的函数是许多科学软件包中使用的一种常见的数值python习语,而使用map
将其应用于iterable显然是一种反模式。但是如果函数是通用的(并且不能利用numpy的矢量化),那么列表comp。或者地图是去的路。@jme很有趣,谢谢!这种isinstance
方法非常脆弱-如果输入是一个浮点
?最好使用e