次のコード
a =func()
if a != None:
b.append(a)
aはNoneに割り当てることができますが、ifステートメントを回避してコードを1行だけ使用する方法はありますか?
元の問題は次のとおりです
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')
Func()を事前に呼び出すことができ、テストステートメントと割り当てステートメントを1つのステートメントに結合する場合は、if-else式を使用してこれを行うことができます。
_b += [a] if a is not None else []
_
AがNoneでない場合、これは[a]をbに追加します-基本的にb.append(a)と同じ操作です
A is Noneの場合、[]がbに追加され、bは変更されません。
これは、bがリストであるか、少なくとも「+ =インプレース追加」をサポートしない限り機能しません。そうでない場合-おそらくそれがいくつかのカスタムオブジェクトである場合、これを行うことができるはずです:
_(b.append(a) if a is not None else None)
_
これは式であり、その副作用について評価された後、破棄されます。 aがNoneの場合、b.append(a)
呼び出しは実行されません。どちらの場合でも、式の値はNoneですが、気にしないので無視されます。
Func()呼び出しをこれと組み合わせる場合は、funcを2回呼び出すことを回避するために、別のことを行う必要があります。 「+ =」構文を使用できる場合は、次のように実行できます。
_b += filter(None, [func()])
_
filter(None, <list>)
は、すべての偽要素(含まれていないが0と[]も含む)が削除されたリストを返します。次に、このステートメントは[func()]または[]をbに追加します。
[編集済み]
最後に、最悪のシナリオの場合:func()を2回以上呼び出すことができない場合、andは使用できません_b += <list>
_、andが必要です0、 ""、[]などを受け入れ、None
、andのみを除外するには、1行ですべてが必要です。ここでは、最も醜いコード行を示します。
_(lambda l, a: l.append(a) if a is not None else None)(b, func())
_
これは基本的に@ekhumoroのソリューションで、1行に圧縮されています。副作用のために、無名関数を定義して呼び出し、値を破棄し、関数を破棄します。
さて、これは1行ですが、元のコードよりも読みやすく、理解するのも容易ではありません。もし私があなただったら、私はオリジナルにこだわるか、ヘルパー関数を定義してそれを使用するという@ekhumoroのアイデアを採用します。
ここで間違った質問をしました。手がかりは、「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行で実行します。
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の新機能です。
短い答え:そうではありません。
より長い答え:これを本当に避けたい場合は(おそらく、この動作を実装したい-----非None値のみを追加したい)-いくつかの異なるコードブロックから)、基になる周りのプロキシとしてクラスを作成できます- bオブジェクトを追加し、appendメソッドで詳細を非表示にします。
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)
しかし、これがあなたのコードにとってまったく意味があるとは思えません。
おそらく、コードから単一の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'))