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

时间:2016-02-28 08:52:56

标签: python function python-2.7

下面的代码有效,但看起来非常难看。我正在寻找一种更加pythonic的方式来写同样的东西。

目标: 对返回多个值的函数的结果做出反应。

示例功能

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

这将返回True和一个字符串(如果字符串与“la”相符),或者返回False,没有任何内容。

在第二个函数中,我将 myfilterfunc 作为可选参数传递

def mymainfunc(mystr,filterfunc=None):

此功能填写返回列表。 如果未给出任何功能,则不会过滤结果并按原样添加。 如果给出了过滤函数,则返回过滤函数 是的,添加了返回的字符串。 (这只是一个例子 轻松使用一个返回值,但我正在尝试获取systax 适合更复杂的设置)

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

任何想法如何在不使用临时变量来存储函数的返回值的情况下编写它?

下面的完整“工作”测试代码

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)

2 个答案:

答案 0 :(得分:1)

如果这种情况经常发生,你可以将丑陋分解出来:

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

一样使用
returnlist.append(filtered(filterfunc, mystr[startpos:nextitem]))

因此,如果您有许多类似的可选过滤器,则代码仍然可读。这是有效的,因为在Python函数/闭包中是一等公民,你可以像其他值一样传递它们。

但是如果逻辑是关于总是添加(过滤或未过滤),为什么不写过滤器以在失败的情况下返回输入而不是(False, "")

这会使代码更容易理解......

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

答案 1 :(得分:0)

我认为您的问题有两种更好的方法,不涉及使用两个返回值。

第一种是简单地返回一个布尔值而不是一个字符串。如果您的过滤器始终返回未经修改的字符串,如果它返回一个字符串(例如,如果第一个值为True),则此方法有效。这种方法可以让你完全避免使用临时值:

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

(注意,如果你走这条路,我建议你将filterfunc重命名为predicate。)

如果某些filterfunc可能返回的值不同于在某些情况下传递的第二个值,则另一个选项将起作用,但绝不会使用2个元组True, None。在这种方法中,您只需使用单个值作为信号和有效负载。如果是None,则忽略它。如果是其他任何东西,你可以使用它。这确实需要一个临时变量,但只需要一个(并且它不那么难看)。

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