質問

もっと簡単な方法があると思いますが、私には思いつきませんでした。

リストを返す多数のメソッドを呼び出しています。リストは空である可能性があります。リストが空でない場合は、最初の項目を返します。それ以外の場合は、None を返します。このコードは動作します:

my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None

これを行うための単純な 1 行のイディオムがあるはずだと私には思えますが、私には一生思いつきません。ありますか?

編集:

ここで 1 行の式を探している理由は、非常に簡潔なコードが好きだからではなく、次のようなコードを大量に書かなければならないからです。

x = get_first_list()
if x:
    # do something with x[0]
    # inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
    # do something with y[0]
    # inevitably forget the [0] part AGAIN, and have another bug to fix

私がやりたいことは、関数を使用して確実に実現できます (おそらくそうなるでしょう)。

def first_item(list_or_none):
    if list_or_none: return list_or_none[0]

x = first_item(get_first_list())
if x:
    # do something with x
y = first_item(get_second_list())
if y:
    # do something with y

私が質問を投稿したのは、Python の単純な式で何ができるかに頻繁に驚かされるためであり、単純な式で機能するのであれば、関数を書くのは愚かなことだと思ったからです。しかし、これらの回答を見ると、それは関数のように思えます シンプルな解決策。

役に立ちましたか?

解決

はPython 2.6 +

next(iter(your_list), None)

your_listNoneできる場合:

next(iter(your_list or []), None)

はPython 2.4

def get_first(iterable, default=None):
    if iterable:
        for item in iterable:
            return item
    return default

例:

x = get_first(get_first_list())
if x:
    ...
y = get_first(get_second_list())
if y:
    ...

別のオプションは、上記の関数をインライン化することです。

for x in get_first_list() or []:
    # process x
    break # process at most one item
for y in get_second_list() or []:
    # process y
    break

あなたが書くことができbreakを回避するには:

for x in yield_first(get_first_list()):
    x # process x
for y in yield_first(get_second_list()):
    y # process y

ここで、

def yield_first(iterable):
    for item in iterable or []:
        yield item
        return

他のヒント

最善の方法はこれです:

a = get_list()
return a[0] if a else None

また、1つのラインでそれを行うことができますが、それはプログラマが読むことのためにはるかに困難です。

return (get_list()[:1] or [None])[0]
(get_list() or [None])[0]

これは動作するはずです。

それは、組み込みlist機能が上書きされるため、

ところで、私は、変数list()を使用していませんでした。

編集:私は少し単純だったが、ここでは、以前の間違ったバージョン

ほとんどのpython慣用的な方法は、リストには、の反復可能なのであるから、イテレータ上)(次を使用することです。ただJ.F.Sebastian @ 2011年12月13日にコメントを入れどのような。

next(iter(the_list), None) the_listが空の場合、これはNoneを返します。参照次の()はPython 2.6+

あなたは確かthe_listのために知っていれば、

または空ではありません。

iterator.next(参照iter(the_list).next()のPython 2.2以降

OP の解決策はほぼ完成しています。OP をより Python らしくするためのことがいくつかあります。

まず、リストの長さを取得する必要はありません。Python の空のリストは、if チェックで False と評価されます。ただ単純に言ってください

if list:

さらに、予約語と重複する変数に代入するのは非常に悪い考えです。「list」は Python の予約語です。

それを次のように変更しましょう

some_list = get_list()
if some_list:

ここでの多くのソリューションが見逃している本当に重要な点は、 すべての Python 関数/メソッドはデフォルトで None を返します. 。以下を試してみてください。

def does_nothing():
    pass

foo = does_nothing()
print foo

関数を早期に終了するために None を返す必要がない限り、明示的に None を返す必要はありません。非常に簡潔に言うと、最初のエントリが存在する場合は、それを返すだけです。

some_list = get_list()
if some_list:
    return list[0]

そして最後に、おそらくこれは暗示されていたのですが、明確に言っておきます(なぜなら、 明示的な方が暗黙的なものよりも優れています)、関数に別の関数からリストを取得させるべきではありません。それをパラメータとして渡すだけです。したがって、最終的な結果は次のようになります

def get_first_item(some_list): 
    if some_list:
        return list[0]

my_list = get_list()
first_item = get_first_item(my_list)

先ほども言いましたが、OP はもうすぐそこまで来ており、ほんの少し手を加えるだけで、求めている Python の風味が得られます。

:あなた自身がリスト内包から最初(またはNone)を摘み取るしようとして見つけた場合は、

あなたは次のようにそれを行うには発電機に切り替えることができます

next((x for x in blah if cond), None)

プロ:何とかは、刃先交換式コンでない場合は動作します:それはなじみのない構文です。周りのハッキングといえipythonで何かをフィルタリングしながら、それは便利です。

for item in get_list():
    return item

率直に言って、私はより良いイディオムがあるとは思わない:あなたは明確かつ簡潔である - 何のための必要はありません「よりよいです」。たぶん、これは本当に好みの問題です、あなたはif len(list) > 0:if list:を変えることができる - 空のリストは常にfalseと評価されます。

関連ノートで、Pythonは にはないのPerl(しゃれが意図していない!)で、あなたは、可能なクールなコードを取得する必要はありません。
実は、私はPythonで見てきた最悪のコードは、また、非常にクール:-)と完全にunmaintainableだっます。

リスト[0]偽(例えば、空の文字列、またはゼロ)と評価されたときに

ちなみに、私はここで見てきたソリューションのほとんどは考慮していない - この場合には、それらはすべて、なしではなく、正しい要素を返しませんます。

最初の項目を返す Python イディオム、または None?

最も Python 的なアプローチは、最も賛成票を集めた回答で示されているものであり、質問を読んだときに最初にそれが思い浮かびました。これを使用する方法は次のとおりです。まず、空の可能性のあるリストが関数に渡された場合です。

def get_first(l): 
    return l[0] if l else None

そして、リストがから返された場合、 get_list 関数:

l = get_list()
return l[0] if l else None

これを行うための他の方法が説明付きでここに示されています

for

これを行うための賢い方法を考え始めたとき、2 番目にこれが思いつきました。

for item in get_list():
    return item

これは関数がここで終了し、暗黙的に戻り値を返すことを前提としています。 None もし get_list 空のリストを返します。以下の明示的なコードはまったく同じです。

for item in get_list():
    return item
return None

if some_list

以下も提案されました (間違った変数名を修正しました)。これも暗黙的な None. 。これは、発生しない可能性のある反復の代わりに論理チェックを使用するため、上記よりも好ましいでしょう。これにより、何が起こっているのかをすぐに理解しやすくなるはずです。ただし、読みやすさと保守性を重視して作成している場合は、明示的な記述も追加する必要があります。 return None 最後に:

some_list = get_list()
if some_list:
    return some_list[0]

スライス or [None] そして0番目のインデックスを選択します

これは最も賛成票を集めた回答にも含まれています。

return (get_list()[:1] or [None])[0]

スライスは不要であり、メモリ内に追加の 1 項目のリストが作成されます。以下はよりパフォーマンスが向上するはずです。説明する、 or 最初の要素が次の場合、2 番目の要素を返します。 False ブール値のコンテキストでは、次の場合 get_list 空のリストを返す場合、括弧内に含まれる式は「なし」を含むリストを返します。このリストには、 0 索引:

return (get_list() or [None])[0]

次の関数は、最初の項目が次の場合に 2 番目の項目を返します。 True ブール値コンテキストでは、my_list を 2 回参照しているため、三項式と同等です (技術的にはワンライナーではありません)。

my_list = get_list() 
return (my_list and my_list[0]) or None

next

次に、組み込み関数を次のように賢く使用します。 next そして iter

return next(iter(get_list()), None)

説明する、 iter を含む反復子を返します。 .next 方法。(.__next__ Python 3 では。) 次に、組み込み next それを呼びます .next メソッドを呼び出し、イテレータが使い果たされた場合は、指定したデフォルトを返します。 None.

冗長な三項式 (a if b else c)そして旋回して戻ります

以下が提案されましたが、論理は通常、否定的なものよりも肯定的なもののほうがよく理解されるため、逆の方が望ましいでしょう。以来 get_list が 2 回呼び出される場合、結果が何らかの方法でメモ化されていない限り、パフォーマンスが低下します。

return None if not get_list() else get_list()[0]

より良い逆:

return get_list()[0] if get_list() else None

さらに良いのは、ローカル変数を使用して、 get_list は 1 回だけ呼び出され、最初に説明した推奨される Python ソリューションが得られます。

l = get_list()
return l[0] if l else None

イディオムについては、 itertoolsレシピが呼び出さしnthます。

itertoolsレシピから:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)
あなたはワンライナーをしたい場合は、

、例えば、あなたのためのこのレシピを実装したライブラリをインストールすることを検討 more_itertoolsするます:

import more_itertools as mit

mit.nth([3, 2, 1], 0)
# 3

mit.nth([], 0)                                             # default is `None`
# None

もう1つのツールは、 more_itertools.first

mit.first([3, 2, 1])
# 3

mit.first([], default=None)
# None

これらのitertoolsだけではなくリストに、任意の反復可能なため、一般的にスケールます。

好奇心から、私は解決策の2にタイミングを走りました。途中でループのために少し高価なのPython 2.5.1と私のマシン上で終了するreturnステートメントを使用するソリューションは、私はこれは反復可能の設定に関係している疑います。

import random
import timeit

def index_first_item(some_list):
    if some_list:
        return some_list[0]


def return_first_item(some_list):
    for item in some_list:
        return item


empty_lists = []
for i in range(10000):
    empty_lists.append([])

assert empty_lists[0] is not empty_lists[1]

full_lists = []
for i in range(10000):
    full_lists.append(list([random.random() for i in range(10)]))

mixed_lists = empty_lists[:50000] + full_lists[:50000]
random.shuffle(mixed_lists)

if __name__ == '__main__':
    ENV = 'import firstitem'
    test_data = ('empty_lists', 'full_lists', 'mixed_lists')
    funcs = ('index_first_item', 'return_first_item')
    for data in test_data:
        print "%s:" % data
        for func in funcs:
            t = timeit.Timer('firstitem.%s(firstitem.%s)' % (
                func, data), ENV)
            times = t.repeat()
            avg_time = sum(times) / len(times)
            print "  %s:" % func
            for time in times:
                print "    %f seconds" % time
            print "    %f seconds avg." % avg_time

これは、私が得たタイミングがあります:

empty_lists:
  index_first_item:
    0.748353 seconds
    0.741086 seconds
    0.741191 seconds
    0.743543 seconds avg.
  return_first_item:
    0.785511 seconds
    0.822178 seconds
    0.782846 seconds
    0.796845 seconds avg.
full_lists:
  index_first_item:
    0.762618 seconds
    0.788040 seconds
    0.786849 seconds
    0.779169 seconds avg.
  return_first_item:
    0.802735 seconds
    0.878706 seconds
    0.808781 seconds
    0.830074 seconds avg.
mixed_lists:
  index_first_item:
    0.791129 seconds
    0.743526 seconds
    0.744441 seconds
    0.759699 seconds avg.
  return_first_item:
    0.784801 seconds
    0.785146 seconds
    0.840193 seconds
    0.803380 seconds avg.
try:
    return a[0]
except IndexError:
    return None
def head(iterable):
    try:
        return iter(iterable).next()
    except StopIteration:
        return None

print head(xrange(42, 1000)  # 42
print head([])               # None

ところで:私はこのような何かにあなたの一般的なプログラムの流れをリワークしたい:

lists = [
    ["first", "list"],
    ["second", "list"],
    ["third", "list"]
]

def do_something(element):
    if not element:
        return
    else:
        # do something
        pass

for li in lists:
    do_something(head(li))

(繰り返し可能な限り回避)

これはどうます:

(my_list and my_list[0]) or None

注:これは、オブジェクトのリストのために正常に動作する必要がありますが、それは以下のコメントあたり数または文字列リストの場合には間違った答えを返すことがあります。

と-やトリックを使用します:

a = get_list()
return a and a[0] or None

そして、何について:next(iter(get_list()), None)? ここでは最速の一つであるが、標準的な(のPython 2.6から開始)と簡潔でない可能性があります。

おそらくない最速のソリューションが、誰も、このオプションを言及していない。

dict(enumerate(get_list())).get(0)

get_list()Noneを返すことができる場合に使用することができます:

dict(enumerate(get_list() or [])).get(0)

長所ます:

- オンライン

- あなたは一度だけget_list()を呼び出す

を理解する - 簡単

私のユースケースは、ローカル変数の値を設定することだけだった。

個人的に私がしようとすると、スタイルクリーナー以外は読むことを見つけます。

items = [10, 20]
try: first_item = items[0]
except IndexError: first_item = None
print first_item

リストをスライスよります。

items = [10, 20]
first_item = (items[:1] or [None, ])[0]
print first_item
if mylist != []:

       print(mylist[0])

   else:

       print(None)

何人かがこのような何かをやって提案しています

list = get_list()
return list and list[0] or None

多くのケースで動作しますが、[0]のリストは0、FALSE、または空の文字列と等しくない場合にのみ動作すること。 [0]リストは0、FALSE、または空の文字列である場合は、この方法が誤ってNoneを返します。

  
    

私は自分のコードで1つのあまりにも多くの時間をこのバグを作成しました!

  

C-スタイル三項演算子に慣用のpythonと同等ではありません
cond and true_expr or false_expr

すなわち。

list = get_list()
return list and list[0] or None
scroll top