python 函数能足够聪明地显示它的能力吗?

发布于 2024-10-15 02:56:08 字数 4805 浏览 2 评论 0原文

我想定义一个可以使用给定的初始参数链接和调用的函数集群,然后得到最终结果,我希望它可以充当Linux命令管道链:

                     test01() | test02() | test03() | test04()
[init_parameter]  ---------------------------------------------------->  [final result]

我正在考虑可以添加函数序列/减少/重新混合,例如:

                     test02() | test03() | test01() | test04()
[init_parameter]  ---------------------------------------------------->  [final result]
                      test03()| test01() | test04() | test01() 
[init_parameter]  ---------------------------------------------------->  [final result]

我还希望这些函数可以嵌入其能力指示器,可用于预先检测智能参数,例如,如果输入不是该函数可以接受的类型或输入超出其最大处理能力,可以在此计算流上忽略该链,而不是使用“try... except...”来捕获那些“逻辑”错误。

请参阅下面的代码,未经测试,仅用于描述我的想法:

def test01(f_inspect=false, a, **b):
    my_capability = {
        "function_cluster":          "A01", 

        "input_acceptable":          type([]),
        "input_element_acceptable":  type(1),
        "input_length_max":          100,

        "return_type":               type([]),
        "return_element":            type(1),
        "return_length_max":         100,
        }

    if f_inspect:
        return my_capability

    return [x+1 for x in a]           # just sample and may raise error by python such as div 0 


def test02(f_inspect=false, a, **b):
    # similiar as test01

def test03(f_inspect=false, a, **b):
    # similiar as test01

def test04(f_inspect=false, a, **b):
    # similar as test01
#==========================================



#test if function chain is compatible
def f_capability_compatible(current_,next_):
    return True if 
        next_["function_cluster"] == current_["function_cluster"] and
        next_["input_acceptable"] is current_["return_type"]  and
        next_["input_length_max"] >= current_["return_element"]  and
        next_["input_length_max"] >= current_["return_length_max"] 
    return False

foos = [test01,test02,test03,test04]

from itertools import permutations
mypermutations = permutations(foos, 3)    # get permutations of testXX

init_parameter = [x for x in range(1,100)]
dummy_function_parameter = {
        "function_cluster":          "A01", 
        "input_acceptable":          type([]),
        "input_element_acceptable":  type(1),
        "input_length_max":          100,
        "return_type":               type([]),
        "return_element":            type(1)
        "return_length_max":         100,
                          }
chain_flag = [True for x in range(len(mypermutations))]
#[True, True, True, ..... True, True, True, True, True, True, True]

for x in len(mypermutations):
    tmp_para = dummy_function_parameter
    for y in mypermutations[x]:
        test_result = f_capability_compatible(tmp_para,y(f_inspect=true))
        chain_flag[x] = test_result
        tmp_para = y(f_inspect=true)
        if test_result == False :
            print "this can not be chained due to parameter incompatible at position %s" %x 
            break

#==========================================
result_of_chain = []
# to invoke:
for x in len(mypermutations):
    if chain_flag[x] == True:
        try :
            # invoking my_capability[x] chain in a go
            tmp_return = init_parameter
            for f in mypermutations[x]:
                tmp_return = f(tmp_return)  #parameter of testXX(a)
        except :
            result_of_chain[x] = "Error"
    else:
        result_of_chain[x] = "Incomp"

这是我的问题, 有没有可能让这个功能链和组合思路更简单一点?

================================== =================================================== =====

更新为什么我需要谓词参数和返回类型:

在linux命令行中,我们可以使用这样的命令:

$ cat sometfile | grep something | awk '{print $0}' | grep something > file

这有效,因为这些命令之间的数据流可以被认为是“文本”类型。

而在Python中,对于那些未知的函数,基本上输入参数和返回结果都有多种类型的可能性。如果我想调用这些函数,我必须知道它的定义。例如

>>> def str_in_asciiout_out(str):
    return ord(str)
>>> 
>>> str_in_asciiout_out("a")
97
>>> str_in_asciiout_out(100)                 
# oops, I have to, try… expect…

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    str_in_asciiout_out(100)
  File "<pyshell#0>", line 2, in str_in_asciiout_out
    return ord(str)
TypeError: ord() expected string of length 1, but int found

Try... except... 是正确且正确的编码方式。

但如果我想组合数百个 str_in_asciiout_out() 类似的函数并将它们放入一个未知的序列中,我关注的是该序列可以在短时间内提供的最佳最终结果。

举个例子,只是举个例子 假设我定义了 1000 个函数,每个函数可能需要运行一天才能根据给定的输入获取输出,我随机挑选 200 个函数放入一个链中,并且 str_in_asciiout_out(100) 运气不好就排在最后,哎哟,浪费了199个小时。

这就是为什么我想在浪费时间的调用之前知道该函数是否可以显示它的能力。

上面的代码是我知道的一个丑陋的解决方案,所以我粘贴这个想法,看看是否有更好的解决方案来解决我的问题。

I want to define a function cluster can be chained and invoked in-a-go with the initial parameter given then get the final result, I want it may acting as Linux command pipe chain:

                     test01() | test02() | test03() | test04()
[init_parameter]  ---------------------------------------------------->  [final result]

I am in condsidering the functions sequence can be added/reduced/remixed, for example:

                     test02() | test03() | test01() | test04()
[init_parameter]  ---------------------------------------------------->  [final result]
                      test03()| test01() | test04() | test01() 
[init_parameter]  ---------------------------------------------------->  [final result]

I also want those functions may come with its ability indicator embedded which can be used for smart parameter pre-detected, for example, if input is not the type this function can accept or input exceed its max process ability, the chain can be just ignored on this calculation stream instead of using "try...except..." to catch those "logic" error.

See below code, untested, just for describing my idea:

def test01(f_inspect=false, a, **b):
    my_capability = {
        "function_cluster":          "A01", 

        "input_acceptable":          type([]),
        "input_element_acceptable":  type(1),
        "input_length_max":          100,

        "return_type":               type([]),
        "return_element":            type(1),
        "return_length_max":         100,
        }

    if f_inspect:
        return my_capability

    return [x+1 for x in a]           # just sample and may raise error by python such as div 0 


def test02(f_inspect=false, a, **b):
    # similiar as test01

def test03(f_inspect=false, a, **b):
    # similiar as test01

def test04(f_inspect=false, a, **b):
    # similar as test01
#==========================================



#test if function chain is compatible
def f_capability_compatible(current_,next_):
    return True if 
        next_["function_cluster"] == current_["function_cluster"] and
        next_["input_acceptable"] is current_["return_type"]  and
        next_["input_length_max"] >= current_["return_element"]  and
        next_["input_length_max"] >= current_["return_length_max"] 
    return False

foos = [test01,test02,test03,test04]

from itertools import permutations
mypermutations = permutations(foos, 3)    # get permutations of testXX

init_parameter = [x for x in range(1,100)]
dummy_function_parameter = {
        "function_cluster":          "A01", 
        "input_acceptable":          type([]),
        "input_element_acceptable":  type(1),
        "input_length_max":          100,
        "return_type":               type([]),
        "return_element":            type(1)
        "return_length_max":         100,
                          }
chain_flag = [True for x in range(len(mypermutations))]
#[True, True, True, ..... True, True, True, True, True, True, True]

for x in len(mypermutations):
    tmp_para = dummy_function_parameter
    for y in mypermutations[x]:
        test_result = f_capability_compatible(tmp_para,y(f_inspect=true))
        chain_flag[x] = test_result
        tmp_para = y(f_inspect=true)
        if test_result == False :
            print "this can not be chained due to parameter incompatible at position %s" %x 
            break

#==========================================
result_of_chain = []
# to invoke:
for x in len(mypermutations):
    if chain_flag[x] == True:
        try :
            # invoking my_capability[x] chain in a go
            tmp_return = init_parameter
            for f in mypermutations[x]:
                tmp_return = f(tmp_return)  #parameter of testXX(a)
        except :
            result_of_chain[x] = "Error"
    else:
        result_of_chain[x] = "Incomp"

Here is my question,
It is possible to make this function chain and combination idea more simple?

=======================================================================================

update why I need to predicate the parameter and return type:

In linux command line, we can using command like this:

$ cat sometfile | grep something | awk '{print $0}' | grep something > file

this works because the data stream between those command can be think as the "text" type.

in python, however, for those unknown function, basically there's variety type possibility of the input parameter and return result. If I want to invoking those functions, I have to know the definition of it. For example

>>> def str_in_asciiout_out(str):
    return ord(str)
>>> 
>>> str_in_asciiout_out("a")
97
>>> str_in_asciiout_out(100)                 
# oops, I have to, try… expect…

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    str_in_asciiout_out(100)
  File "<pyshell#0>", line 2, in str_in_asciiout_out
    return ord(str)
TypeError: ord() expected string of length 1, but int found

Try... except... is right and proper way to code.

But if I want to combine hundreds of str_in_asciiout_out() alike functions and put them into an unknown sequence, what I focused is the best final result the sequence can delivered in short time.

For example, just example
Suppose I have 1000 functions defined, each function may need to run one day to get the output by given input, I random picked 200 functions into a chain, and the
str_in_asciiout_out(100)
just on the last position by bad luck, I may got an oops until wasted 199 hours.

That’s why I want to know if the function can show it’s ability before the time-wasting invoking.

Above code is an ugly solution I known, so I paste the idea to see if there’s better solution for my problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

季末如歌 2024-10-22 02:56:08

我最近看了一个关于 Python 生成器 的幻灯片演示,其中介绍了很多你可以做的巧妙的事情与生成器函数一起使用,允许您像管道和过滤器系统一样使用它们。它们也会被“惰性”评估,因此当您处理一个很长的列表时,它只会处理第一个列表中需要的部分,以便为您提供生成器的第一个输出。

看起来您正试图将静态类型硬塞到 Python 中。虽然存在静态类型的情况,但我不确定尝试以这种方式在应用程序级别将其强制转换为动态语言是否是一个好主意。您试图防止的这种情况可以通过在小输入上测试代码来改进

最后,如果您尝试使用有关其返回类型的元数据来注释函数,最好使用 函数的装饰器。例如,如果您热衷于使用类型,则可以使用类似这样的 示例来自装饰器 PEP 的装饰器

def attrs(**kwds):
    def decorate(f):
        for k in kwds:
            setattr(f, k, kwds[k])
        return f
    return decorate

@attrs(argument_types=(int, int,),
       returns=int)
def add(a, b):
    return a + b

然后,您可以只访问 add.argument_typesadd,而不是使用 f_inspect 参数调用函数。返回add成员变量。

I recently saw a slide presentation on Python generators that went through a lot of neat things you can do with generator functions that allows you to use them like a pipe-and-filter system. They're also evaluated "lazily", so when you process, say, a very long list, it will only process the portion that it needs to of the first list in order to give you the first output of the resulting generator.

It looks here like you're kind of trying to shoehorn static typing into Python. While there are cases for static typing, I'm not sure it's such a good idea to try and force it into a dynamic language at the application level in this manner. The kind of thing you're trying to prevent can be improved by testing your code on small inputs

And lastly, if you're trying to annotate functions with metadata about their return types, it would be better to use a decorator for the function. For instance, if you were heartset on using types, you could use something like this example decorator from the Decorators PEP:

def attrs(**kwds):
    def decorate(f):
        for k in kwds:
            setattr(f, k, kwds[k])
        return f
    return decorate

@attrs(argument_types=(int, int,),
       returns=int)
def add(a, b):
    return a + b

Then, rather than calling the function with a f_inspect parameter, you could just access the add.argument_types and add.returns member variables of add.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文