Python: избегать ли условие для этого кода? - PullRequest
21 голосов
/ 12 января 2012

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

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)

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

Ответы [ 6 ]

21 голосов
/ 12 января 2012

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

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

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

Если 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 просто определить вспомогательную функцию и использовать ее.

5 голосов
/ 12 января 2012

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

Атакую ​​вашу настоящую проблему и делаю это в две строки для ясности:

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

0 голосов
/ 12 января 2012

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

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

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

0 голосов
/ 12 января 2012

Предположительно, вы не пытаетесь удалить только один оператор 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'))
0 голосов
/ 12 января 2012

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

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

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

Все еще не очень аккуратно, хотя.На вашем месте я бы сохранил это if заявление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...