0

据我了解,Python lambda 只允许表达式,而不是语句。我有一个案例,我len()在 lambda 表达式中使用并试图获取函数调用的返回值的长度。但是,该函数调用有可能返回None,这会中断len()。有没有一种优雅的方式来解决这个问题?

例子:

def foo(obj_list, field):
    return maxk(obj_list, key=lambda obj: len(nested_getattr(obj, field)))

在上面,maxk()是一个max()接受key参数的版本。我在 Python 2.4 上(目前不能使用更高版本),所以我有一个自定义实现,max()它需要一个关键参数,来自这里(请参阅帖子 #140122 和 #140143)。 nested_getattr()是另一个效用函数,其作用类似于getattr()但可以获取嵌套在另一个属性中的属性。这可以从这里获得

示例函数的作用(这是我使用更改变量/名称的实际函数)是通过对象列表 ( obj_list) 并比较值的长度field并返回列表field中总体最大的对象。

但是,如果field为每个对象指定的属性返回None,那么len()将被 阻塞TypeError。我想我可以使用内联条件来解决这个问题,但是我必须调用nested_getattr()两次,一次进行检查,如果返回值不是,则可能再调用一次None。我宁愿将它的返回值缓存到一个变量中,并在决定返回什么之前有条件地运行它(或者只是让生成器表达式完全跳过它)。

有什么好的方法来处理这个?我对这个函数的其他实现持开放态度maxk(),或者nested_getattr()(如果需要)。

4

4 回答 4

5

只需将函数单独定义为常规函数,然后将其传递给 maxk:

def getLen(obj):
    val = nested_getattr(obj, field)
    if val is None:
        return 0
    else:
        return len(val)
return maxk(obj, key=getLen)

Lambdas are meant to be used when it is easier to write an inline single-expression function that it would be to write a separate function. If it becomes harder to think of how to write the lambda than to just write a normal function, just write a normal function. There's no point spending time how to fit it into a lambda, because the lambda doesn't gain you anything in that case.

Edit: Lambdas are bytecode-identical to non-lambda functions that do the same thing.

>>> f = lambda x: x**2
>>> def g(x):
...     return x**2
>>> import dis
>>> dis.dis(f)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (2)
              6 BINARY_POWER        
              7 RETURN_VALUE        
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (2)
              6 BINARY_POWER        
              7 RETURN_VALUE     
于 2012-09-26T22:45:32.727 回答
3

Maybe this:

lambda val: len(val or [])
于 2012-09-26T22:54:55.913 回答
2

You could add the third argument to nested_getattr() with the same meaning as the third argument of getattr():

len(nested_getattr(obj, field, ''))  

Also in this particular case len(nested_getattr(obj, field) or '')) (suggested by @DSM) works fine if possible returned values are sequences and None.

一般来说,@BrenBarn 建议的命名函数可能更可取。

于 2012-09-26T22:56:02.533 回答
0
def foo(obj_list, field):
    return maxk(obj_list, key=lambda obj: len(nested_getattr(obj, field) or []))

I can't test on 2.4 right now, but this works in 3.2.

于 2012-09-26T22:53:28.407 回答