Python: избегать, если условие для этого кода?

для следующего кода

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)

ok, я использовал все ответы и получил это, лично я считаю, что это самый сложный питон, который я когда-либо писал, lol

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')

Ответ 1

Если вы можете вызвать func() заранее, и вы хотите совместить операторы теста и присваивания в один оператор, вы можете сделать это с помощью выражения if-else:

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

Если a не является None, то это добавит [a] в b - по существу ту же операцию, что и b.append(a)

Если a равно None, это добавит [] в b, что не изменит значение b.

Это не сработает, если b не является списком или, по крайней мере, поддерживает добавление "+ =" на месте. Если это не так - возможно, это какой-то пользовательский объект, тогда вы должны это сделать:

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

Это выражение, оценивается по его побочным эффектам, а затем выбрасывается. Если a равно None, вызов b.append(a) никогда не будет выполнен. В любом случае значение выражения равно None, но мы не заботимся об этом, поэтому его игнорируют.

Теперь, если вы хотите объединить вызов func() с этим, вам нужно будет сделать что-то другое, чтобы избежать вызова функции дважды. Если вы можете использовать синтаксис "+ =", вы можете сделать это следующим образом:

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

filter(None, <list>) возвращает список со всеми ложными элементами (None included, а также 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 просто определить вспомогательную функцию и использовать ее.

Ответ 2

Здесь вы задали неправильный вопрос. Подсказка в вашем ответе на один из комментариев, где вы говорите: "У меня есть теги 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)

Ответ 3

Атакуйте свою реальную проблему и делайте это в двух строках для ясности:

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

Ответ 4

Предположительно, вы не пытаетесь удалить только один оператор 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

Короткий ответ: Не совсем.

Более длинный ответ: если вы действительно хотели этого избежать (возможно, потому, что вы хотите реализовать это поведение, добавляя только значения, отличные от 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)

Однако я не уверен, что это будет иметь смысл для вашего кода.

Ответ 7

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

Но это очень уродливо. Немного чище, но и длиннее:

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

Тем не менее, не очень аккуратный. Если бы я был вами, я бы просто сохранил этот оператор if.