0

假设我的列表只有strand 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

但否定条件不起作用:

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

它返回AttributeError

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

3 回答 3

3

您正在测试是否i is not None or i.isupper(). i 这在is 时不起作用None

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

被懒惰地评估;首先评估左侧,并且仅当False评估第二个参数。第一个是 only Falseif iis None,所以右手表达式只会被评估为None.isupper()

改为使用and,并否定isupper()测试:

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

上面的表达式是 的正确逻辑反转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
于 2013-08-21T12:46:29.640 回答
2

在返回 an 的代码中AttributeError,这是因为如果 i没有,它会继续到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']
于 2013-08-21T12:52:13.450 回答
1

我喜欢@Brionius 的编辑答案,这是它的一种更通用的形式,它从列表中返回项目的字典,由判别函数返回的值作为键(可能返回的不仅仅是 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'))

给予:

{False: [None, None, None], True: ['foo', 'FOO', 'bar']}
{0: [None, None, None], 3: ['foo', 'FOO', 'bar']}
{False: [None, 'foo', None, None, 'bar'], True: ['FOO']}
{1: ['bar'], 2: ['foo', 'FOO'], None: [None, None, None]}

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

def splitItems(seq, condition):
    ret = groupByEval(seq, condition)
    return ret.get(True,[]), ret.get(False,[])
于 2013-08-21T13:37:50.377 回答