Python:避免这个代码的条件?

时间:2012-01-11 20:58:48

标签: python if-statement flow-control

以下代码

a =func()
if a != None:
    b.append(a)

a可以分配给None,有没有办法避免使用if语句而只使用一行代码?

原始问题如下

import xml.etree.ElementTree as etree

r = etree.parse(f).getroot()
b = etree.Element('register',{})

a = r.find('tag_name') # a may get None if did not find it
if a != None:
    b.append(a)
好吧,我使用了所有答案并得到了这个,我个人认为它是迄今为止我写过的最复杂的python,大声笑

NS_MAP = {
    'spirit' : 'http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.4',
    'app' : 'http://www.app.com/SPIRIT-app'
    }

mp=etree.Element('MemoryProperty', {'version':'alpha'})
mpt=etree.ElementTree(mp)


def copy_tags(tp, op, p, tn, ns='spirit'):
    c =  p.find('{%s}%s'%(NS_MAP[ns],tn))
    if c is not None:
        (op == '<-') and tp.append(c)
        return c    

for reg in regs:
    te = etree.Element('register',{})
    copy_tags(te,'<-',reg,'name')
    copy_tags(te,'<-',reg,'addressOffset')
    copy_tags(te,'<-',reg,'access')
    (lambda e, t: copy_tags(te,'<-',t,'usageConstraints',ns='app') if t is not None else None)(te, copy_tags(te,'|',reg,'vendorExtensions'))

    mp.append(te)

mpt.write('map_gen.xml')

7 个答案:

答案 0 :(得分:20)

如果你可以事先调用func(),并且想要将测试语句和赋值语句组合成一个语句,那么可以使用if-else表达式执行此操作:

b += [a] if a is not None else []

如果a不是None,那么这会将[a]添加到b - 基本上与b.append(a)相同的操作

如果无,那么这会将[]添加到b,这将使b保持不变。

除非b是列表,或者至少支持“+ =”就地添加,否则这将不起作用。如果没有 - 也许它是一些自定义对象,那么你应该能够做到这一点:

(b.append(a) if a is not None else None)

这是一个表达式,评估其副作用,然后扔掉。如果a为None,则永远不会执行b.append(a)调用。在任何一种情况下,表达式的值都是None,但我们不关心它,因此它会被忽略。

现在,如果你想将func()调用与此结合,那么你将不得不做一些不同的事情,以避免两次调用func。如果您可以使用“+ =”语法,那么您可以这样做:

b += filter(None, [func()])

filter(None, <list>)返回列表,其中包含所有错误元素(包括无,但也包括0和[])。然后,该语句将[func()]或[]添加到b。

<强> [编辑]

最后,对于最坏的情况:如果你不能多次调用func(),你就不能使用b += <list>你需要接受0,“”,[]等,只排除None,你需要在一行中完成所有这些,这里是最丑陋的代码行:

(lambda l, a: l.append(a) if a is not None else None)(b, func())

这基本上是@ ekhumoro的解决方案,压缩成一行。它定义了一个匿名函数,调用它,丢弃该值,然后丢弃该函数,所有这些都是为了副作用。

现在,这是一行,但它比原始代码更难阅读或理解。如果我是你,我会坚持使用原版,或者使用@ ekhumoro关于定义辅助函数并使用它的想法。

答案 1 :(得分:5)

你在这里问了一个错误的问题。线索在你对其中一条评论的回复中,你说“我有10个以上的标签,如果我能获得3行到1行,我将节省20多行”。

所以你的问题实际上不是你有3行代码,而是你不必要地反复重复3行代码。您可以使用函数来提取重复的行,但听起来在这种情况下您实际上可能需要一个循环:

THE_TAGS = ('tag1', 'tag2', 'and so on')
for tag in THE_TAGS:
    a = r.find(tag) # a may get None if did not find it
    if a != None:
        b.append(a)

或者,如果您需要附加到不同的列表:

def extract_tag(r, tag_name, to):
    a = r.find(tag_name) # a may get None if did not find it
    if a != None:
        to.append(a)

extract_tag(r, 'tag1', b)
extract_tag(r, 'tag2', c)

答案 2 :(得分:2)

为了清晰起见,攻击你的真实问题并将其分为两行:

temp = [r.find(tag) for tag in list_of_tags]
b.extend(x for x in temp if x is not None)

注意:Element.extend是Python 2.7 / 3.2中的新功能

答案 3 :(得分:1)

python 3.8 walrus operator

if a := func(): b.append(a)

答案 4 :(得分:0)

据推测,您并不是要从代码中删除一个if语句...

所以显而易见的答案是使用一个函数:

import xml.etree.ElementTree as etree

def append(parent, child):
    if child is not None:
        parent.append(child)

r = etree.parse(f).getroot()
b = etree.Element('register',{})

append(b, r.find('tag_name'))

答案 5 :(得分:0)

简短回答:不是。

更长的答案:如果你真的想避免这种情况(也许是因为你想要从几个不同的代码块中实现这种行为---只附加非None值)那么你可以创建一个类作为代理基础 b 对象并在其追加方法中隐藏细节。

class NonNoneAppender:
    def __init__(self, obj):
        if not hasattr(obj, 'append') or not callable(obj.append):
            raise ValueError, "Object must have append method"
        self.__obj = obj
    def append(self, item):
        if item is not None:
            return self.__obj.append(item)
    def __getattr__(self, attr):
        return getattr( self.__obj, attr)      

...然后你可以做类似的事情:

b = NonNoneAppender(b)

但是,我不确定这对你的代码是否有任何意义。

答案 6 :(得分:-1)

b+=list(set([r.find('tag_name')])-set([None]))

但它非常难看。一点点清洁,但也更长一点:

b.append(r.find('tag_name'))
b.remove(None)

虽然不是很整洁。如果我是你,我会保留if声明。