gpt4 book ai didi

python - 函数如何接受冒号(范围运算符)作为参数(在 Python 中)?

转载 作者:行者123 更新时间:2023-12-01 04:58:34 24 4
gpt4 key购买 nike

我想要执行以下操作:我想要定义一个递归函数 funct,其中自身的最后一个引用返回数组 temp 的数字。问题是 funct 必须对自身进行积分(请参见下面的代码),如果 funct 可以接受冒号 :,这将非常容易> 作为参数。所以,到目前为止我有这个(简化的)代码:

import numpy as np   
import scipy.integrate as ints

temp = np.array([[1,2,3,4,5],[4,0,6,7,8],[7,8,9,10,11],[1,2,3,4,5],[6,7,8,9,10]])

def funct(x,y,n):
if n>1:
return (temp[x,y] + ints.cumtrapz(temp[x,:]*funct(:,y,n-1), x=None, dx=1, initial=0)[-1])
else:
return temp[x,y]
funct = np.vectorize(funct)
funct(1,1,3)

问题是 funct 不能接受冒号 : 作为参数,如果我想向量化到代码后面的 funct

例如,如果我更改上面代码的这部分

ints.cumtrapz(temp[x,:]*funct(:,y,n-1), x=None, dx=1, initial=0)[-1]) 

对于

ints.cumtrapz(temp[x,:]*temp[:,y], x=None, dx=1, initial=0)[-1]) 

我没有任何问题。我只想递归地完成最后一部分。

最佳答案

首先,Python 不像其他语言那样有“范围运算符”。 : 生成 slice,它是与 range 完全不同的类型。而且,更重要的是, : 语法是 slicing 的一部分。 (又名扩展索引或扩展订阅)语法,它并不独立。

因此,编写代码的简单方法是使用 slice 文字:

当然,您也可以避免所有这些困惑,只使用显式切片文字:

def funct(x, y, n):
if n>1:
return (temp[x,y] + ints.cumtrapz(temp[x,:]*funct(slice(None),y,n-1), x=None, dx=1, initial=0)[-1])
else:
return temp[x,y]
<小时/>

那么,为什么没有一种比调用 slice 构造函数更方便的“切片文字”语法呢?因为没有人提出令人信服的论点,解决潜在的语法歧义,并提交补丁。*

* 请注意,Python 确实自己添加了省略号文字的语法 - ...省略号 的文字,省略号类型的单例值。很多人都希望这样,除了已经非法的代码之外,没有任何歧义,有人编写了补丁,并且没有什么大惊小怪就被接受了。

<小时/>

虽然扩展索引的语法和函数调用的语法有些相似,但它们并不相同。这意味着您不能使用函数调用作为特定于域的语言来包装延迟切片。

您可以做的一件事是创建切片包装类型,将切片表达式本身用作特定于域的语言:

class Slicer:
def __getitem__(self, idx):
return idx
s = Slicer()

现在 s[:]slice(None) 的构造函数,而 s[3:23:2, ..., 4](slice(3, 23, 2), Ellipsis, 4) 的构造函数。所以你可以这样写:

funct(s[:,y,n-1])

您的 funct 类将获取一个由 slice 对象和整数组成的元组,稍后可以通过调用其 __getitem__ 来使用它来索引数组直接。

如果您愿意,您可以总结更多内容。例如:

class SliceCallable(object):
def __init__(self, f):
self.f = f
def __getitem__(self, idx):
if isinstance(idx, collections.abc.Sequence):
return self.f(*idx)
else:
return self.f(idx)
def __call__(self, *args):
return self.f(*args)

@SliceCallable
def funct(x, y, n):
if n>1:
return (temp[x,y] + ints.cumtrapz(temp[x,:]*funct[:,y,n-1], x=None, dx=1, initial=0)[-1])
else:
return temp[x,y]

现在,funct 可以被调用为 funct(1, 2, 3)funct[1, 2, 3]——或作为 funct[:, 2, 3]funct[4:-1]。这仅仅意味着x将是slice(None, None, None)slice(4, -1, None)。您可以在索引表达式中使用它; temp[slice(None, None), 3] 可能看起来不如 temp[:, 3] 那么好,但它的意思是一样的。

关于python - 函数如何接受冒号(范围运算符)作为参数(在 Python 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26811712/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com