Python中令人困惑的三元

2024-09-28 22:23:11 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我的列表只有strNone,我想检查assign lowered strings into other variable,但是如果它是大写的或没有的,它应该呈现为None。在

检查Nonestr.isupper()的代码起作用:

for i in [None,'foo',None,'FOO',None,'bar']:
  x = None if i is None or i.isupper() else i
  print x

但否定条件不起作用:

^{pr2}$

它返回AttributeError

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
AttributeError: 'NoneType' object has no attribute 'isupper'
  • 为什么会这样?
  • 除了循环中的三元赋值,是否有其他方法执行相同的操作?

Tags: 代码innone列表forvariableattributeerrorother
3条回答

我喜欢@Brionius'编辑的答案,这里有一个更一般的形式,从列表中返回一个项目的dict,由一个判别函数返回的值(可能返回的不仅仅是True或False)。在

from collections import defaultdict

def groupByEval(seq, fn):
    ret = defaultdict(list)
    for item in seq:
        ret[fn(item)].append(item)
    return dict(ret.iteritems())


test = [None,'foo',None,'FOO',None,'bar']
print groupByEval(test, lambda x: x is not None)
print groupByEval(test, lambda x: 0 if x is None else len(x))
print groupByEval(test, lambda x: x is not None and x.isupper())
print groupByEval(test, lambda x: x if x is None else sum(x.lower().count(c) for c in 'aeiou'))

给予:

^{pr2}$

Brionius的解决方案可以实现为:

def splitItems(seq, condition):
    ret = groupByEval(seq, condition)
    return ret.get(True,[]), ret.get(False,[])

您正在测试i is not None or i.isupper()。当iNone时,这不起作用:

(i is not None) or (i.isupper())

延迟求值;首先计算左边的参数,并且仅当False是第二个被求值的参数时。第一个是False,如果iNone,所以右手表达式只计算为None.isupper()。在

{cde>{cde}而不是^ cd9}:

^{pr2}$

上面的表达式是i is None or i.isupper()的正确逻辑反转。在

或者在原始表达式周围使用not (..)

x = i if not (i is None or i.isupper()) else None

因为您使用的是正则的for循环,因此不需要在这里使用条件表达式;下面将赋值给现有的循环变量i,就足够了:

for i in [None,'foo',None,'FOO',None,'bar']:
      if i and i.isupper():
          i = None
      print i

在返回AttributeError的代码中,这是因为如果inone,它将继续执行or语句的第二部分并检查i.isupper(),但是None没有isupper()方法,因此会出现错误。在

我可以建议另一种方法吗?在

items = [None,'foo',None,'FOO',None,'bar']

def splitItems(items, test):
    trueItems = []
    falseItems = []
    for item in items:
        if test(item):
            trueItems.append(item)
        else:
            falseItems.append(item)
    return trueItems, falseItems

trueItems, falseItems = splitItems(items, lambda i:i is None or i.isupper())
print "uppercase or None:", trueItems
print "lowercase:", falseItems
# uppercase or None: [None, None, 'FOO', None]
# lowercase: ['foo', 'bar']

相关问题 更多 >