简体   繁体   English

更好/更Python化的方式来处理具有多个返回值的函数的结果

[英]Better / More pythonic way to process the results of a function with multiple return values

The code below works, but looks very ugly. 下面的代码可以工作,但是看起来很丑陋。 I'm looking for a more pythonic way to write the same thing. 我正在寻找一种更Python化的方式来编写相同的东西。

The goal: React on a result of a function that returns multiple values. 目标:对返回多个值的函数的结果作出反应。

Example function 示例功能

def myfilterfunc(mystr):
   if 'la' in mystr:
       return True, mystr
   return False, None

This returns True and a string (if the string cointains "la"), or False and nothing. 这将返回True和一个字符串(如果字符串包含“ la”),或者返回False,则不返回任何内容。

In a second function, I'm passing myfilterfunc as an optional parameter 在第二个函数中,我将myfilterfunc作为可选参数传递

def mymainfunc(mystr,filterfunc=None):

This function fills a returnlist. 此函数填充返回列表。 If no function is given, the result is not filtered and added as is. 如果未提供任何功能,则不对结果进行过滤并按原样添加。 If a filter function is given, if the filter function returns True, a returned string is added. 如果指定了过滤器函数,则如果过滤器函数返回True,则添加返回的字符串。 (This is just an example that would easily work with one return value, but I'm trying to get the systax right for a more complicated setup) (这只是一个可以很容易地使用一个返回值的示例,但是我正在尝试为更复杂的设置获取正确的systax)

if filterfunc:
    tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem])
    if tmp_status:
        returnlist.append(tmp_string)
    else:
        returnlist.append(mystr[startpos:nextitem])

Any idea how I can write this without using temporary variables to store the return values of the function? 知道如何在不使用临时变量存储函数返回值的情况下编写此代码吗?

Full "working" test code below 完整的“有效”测试代码如下

def string2list(mystr,splitlist,filterfunc=None):
    returnlist = []
    startpos = 0
    nextitem = -1
    matched = True
    while matched:
        matched = False
        for sub in splitlist:
            if startpos == 0:
                tmpi = mystr.find(sub)
            else:    
                tmpi = mystr.find(sub,startpos + 1)
            if (tmpi > 0) and ((nextitem < 0) or (nextitem > tmpi)):
                nextitem = tmpi
                matched = True
        if filterfunc:
            tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem])
            if tmp_status:
                returnlist.append(tmp_string)
        else:
            returnlist.append(mystr[startpos:nextitem])
        startpos = nextitem 
        nextitem = -1
    return returnlist

def myfilterfunc(mystr):
    if 'la' in mystr:
        return True,mystr
    return False,''    


splitlist = ['li','la']
mytext = '''
li1
li2
li3
fg4
fg5
fg6
la7
la
la
tz
tz
tzt
tz
end
'''



print string2list(mytext,splitlist)
print
print string2list(mytext,splitlist,myfilterfunc)

If this is going to happen often you can factor out the uglyness: 如果这种情况经常发生,您可以排除丑陋之处:

def filtered(f, x):
    if f:
        status, result = f(x)
        return result if status else x
    else:
        return x

used like 使用像

returnlist.append(filtered(filterfunc, mystr[startpos:nextitem]))

so that if you have many similar optional filters the code remains readable. 因此,如果您有许多类似的可选过滤器,则代码仍然可读。 This works because in Python functions/closures are first class citizens and you can pass them around like other values. 之所以可行,是因为在Python函数/闭包中是一等公民,您可以像其他值一样传递它们。

But then if the logic is about always adding (either the filtered or the unfiltered) why not just write the filter to return the input instead of (False, "") in case of failure? 但是,如果逻辑总是要添加(过滤的或未过滤的)逻辑,为什么不写过滤器以返回输入,而不是在失败的情况下返回(False, "")

That would make the code simpler to understand... 这将使代码更易于理解...

returnlist.append(filterfunc(mystr[startpos:nextitem]))

I think there are two better approaches to your problem that don't involve using two return values. 我认为有两种更好的方法可以解决您的问题,而无需使用两个返回值。

The first is to simply return a Boolean value and not a string at all. 首先是简单地返回一个布尔值,而不是一个字符串。 This works if your filter is always going to return the string it was passed unmodified if it returns a string at all (eg if the first value is True ). 如果您的过滤器总是返回字符串,则该方法可以正常工作,如果它完全返回了字符串(例如,如果第一个值为True ),则该过滤器将未经修改地传递。 This approach will let you avoid using temporary values at all: 这种方法将使您完全避免使用临时值:

if filterfunc:
    if filterfunc(mystr[startpos:nextitem]):
        returnlist.append(mystr[startpos:nextitem])

(Note, I'd suggest renaming filterfunc to predicate if you go this route.) (请注意,如果您走这条路线,我建议重命名filterfunc以作为predicate 。)

The other option will work if some filterfunc might return a different second value than it was passed under some situations, but never the 2-tuple True, None . 如果某些filterfunc返回的第二个值可能不同于在某些情况下传递的第二个值,则另一个选项将起作用,但绝不会是2元组True, None In this approach you simply use the single value as both the signal and the payload. 在这种方法中,您只需将单个值用作信号和有效负载。 If it's None , you ignore it. 如果为None ,则忽略它。 If it's anything else, you use it. 如果还有其他用途,请使用它。 This does require a temporary variable, but only one (and it's a lot less ugly). 这确实需要一个临时变量,但只需要一个临时变量(而且丑陋得多)。

if filterfunc:
    result = filterfunc(mystr[startpos:nextitem])
    if result is not None:
        returnlist.append(result)

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

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