문제

나는 나에게 일어나지 않는이 작업을 수행하는 더 간단한 방법이 있다고 확신합니다.

목록을 반환하는 많은 방법을 호출합니다. 목록이 비어있을 수 있습니다. 목록이 비어 있지 않으면 첫 번째 항목을 반환하고 싶습니다. 그렇지 않으면, 나는 아무것도 반환하고 싶다. 이 코드는 작동합니다.

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

이 작업을 수행하기위한 간단한 한 줄의 관용구가 있어야하는 것 같습니다. 그러나 내 삶에는 생각할 수 없습니다. 거기가 있습니까?

편집하다:

내가 여기서 한 줄 표현을 찾고있는 이유는 내가 엄청나게 간결한 코드를 좋아하는 것이 아니라 다음과 같은 많은 코드를 작성해야하기 때문입니다.

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

나는 파이썬의 간단한 표현이 할 수있는 일에 자주 놀랐기 때문에 질문을 게시했으며, 단순한 표현이 있으면 기능을 작성하는 것이 어리석은 일이라고 생각했습니다. 하지만 이러한 대답을 보면 기능처럼 보입니다. ~이다 간단한 솔루션.

도움이 되었습니까?

해결책

파이썬 2.6+

next(iter(your_list), None)

만약에 your_list 할 수 있습니다 None:

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

파이썬 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

한 줄로도 할 수 있지만 프로그래머가 읽기가 훨씬 어렵습니다.

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

작동해야합니다.

BTW 변수를 사용하지 않았습니다 list, 그것은 내장을 덮어 쓰기 때문에 list() 기능.

편집 : 나는 약간 더 단순하지만 이전에는 잘못된 버전이있었습니다.

가장 파이썬 관용적 방법은 목록이기 때문에 반복자에서 다음 ()을 사용하는 것입니다. 반복적 인. @jfsebastian이 2011 년 12 월 13 일에 의견을 제시 한 것과 마찬가지로.

next(iter(the_list), None) 이것은 IF가 반환됩니다 the_list 비었다. 보다 다음 () Python 2.6+

또는 확실히 알고 있다면 the_list 비어 있지 않음 :

iter(the_list).next() 보다 iterator.next () Python 2.2+

OP의 솔루션은 거의 존재합니다. 더 피스닉으로 만드는 몇 가지가 있습니다.

우선 목록의 길이를 얻을 필요가 없습니다. Python의 빈 목록은 IF 검사에서 False로 평가됩니다. 단순히 말하십시오

if list:

또한, 예약 된 단어와 겹치는 변수에 할당하는 것은 매우 나쁜 생각입니다. "목록"은 파이썬의 예약 된 단어입니다.

그러니 바꾸겠습니다

some_list = get_list()
if some_list:

여기에 많은 솔루션이 놓친 정말 중요한 점은 모든 Python 함수/메소드는 기본적으로 아무도 반환하지 않습니다. 다음을 시도하십시오.

def does_nothing():
    pass

foo = does_nothing()
print foo

기능을 조기에 종료하기 위해 아무것도 반환하지 않아도, 명시 적으로 반환 할 필요가 없습니다. 간결하게, 첫 번째 항목이 존재하는 경우 첫 번째 항목을 반환하십시오.

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는 거의 거기에 있었고 몇 번의 터치만으로도 당신이 찾고있는 파이썬 맛을줍니다.

목록 이해력에서 첫 번째 (또는 없음)를 뽑으려고한다면 발전기로 전환하여 다음과 같이 할 수 있습니다.

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

Pro : Blah가 색인이 없으면 작동합니다. Con : 익숙하지 않은 구문입니다. 그래도 Ipython에서 해킹 및 필터링하는 동안 유용합니다.

for item in get_list():
    return item

솔직히 말해서, 나는 더 나은 관용구가 있다고 생각하지 않습니다. 당신은 분명하고 간결합니다 - "더 나은"것은 필요하지 않습니다. 어쩌면, 그러나 이것은 정말 맛의 문제입니다. if len(list) > 0: ~와 함께 if list: - 빈 목록은 항상 거짓으로 평가됩니다.

관련 메모에서는 파이썬이 있습니다 ~ 아니다 Perl (말장난 의도 없음!), 당신은 가장 멋진 코드를 가능하게 할 필요가 없습니다.
실제로, 내가 Python에서 본 최악의 코드는 또한 매우 시원했습니다 :-) 완전히 인재 할 수 없습니다.

그건 그렇고, 여기에서 본 대부분의 솔루션은 List [0]이 False (예 : 빈 문자열 또는 0)로 평가할 때 고려하지 않습니다.

첫 번째 아이템을 반환하는 Python 관용구?

가장 피스닉적인 접근법은 가장 큰 대답이 보여준 것입니다. 질문을 읽을 때 가장 먼저 떠오르는 것이 었습니다. 비어있는 목록이 함수로 전달되는 경우 먼저 사용 방법은 다음과 같습니다.

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

목록이 a에서 반환 된 경우 get_list 기능:

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

다른 방법은 설명과 함께 여기서 이것을하는 것으로 입증되었습니다.

for

내가 이것을하는 영리한 방법을 생각하기 시작했을 때, 이것은 내가 생각한 두 번째 일입니다.

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] Zeroth Index를 선택하십시오

이것은 또한 가장 투명한 답변에 있습니다.

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

슬라이스는 불필요하며 메모리에 추가로 한 항목 목록을 만듭니다. 다음은 더 성능이 있어야합니다. 설명하기, or 첫 번째 인 경우 두 번째 요소를 반환합니다 False 부울 맥락에서 get_list 빈 목록을 반환하면 괄호 안에 포함 된 표현식은 'None'이있는 목록을 반환 한 다음 0 인덱스:

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

다음은 사실을 사용하고 두 번째 항목을 반환합니다. True 부울 맥락에서, My_List를 두 번 언급하기 때문에, 3 원 표현보다 낫지 않습니다 (기술적으로는 하나의 라이너가 아닙니다).

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

next

그런 다음 우리는 다음과 같은 영리한 사용을 가지고 있습니다. next 그리고 iter

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

설명하기, iter 반복자를 a로 반환합니다 .next 방법. (.__next__ 파이썬 3에서.) 그런 다음 내장 next 그것을 부릅니다 .next 방법, 반복자가 소진되면 우리가 제공하는 기본값을 반환합니다. None.

중복 3 가지 표현 (a if b else c) 그리고 돌고 돌고 있습니다

아래는 제안되었지만 논리는 일반적으로 음성 대신 양수로 더 잘 이해되므로 역전이 바람직합니다. 부터 get_list 결과가 어떤 식 으로든 메모 화되지 않는 한, 이것은 성능이 좋지 않을 것입니다.

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

더 나은 역수 :

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

더 나은 것은 로컬 변수를 사용하여 사용하십시오 get_list 한 번만 호출되며 권장 Pythonic 솔루션이 먼저 논의되었습니다.

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

첫 번째 항목 만 반환하는 다른 도구를 사용할 수 있습니다. more_itertools.first.

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

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

이 Itertools는 목록뿐만 아니라 반복 가능한 모든 반복에 대해 일반적으로 척도입니다.

호기심으로, 나는 두 가지 솔루션에서 타이밍을 달렸습니다. 반환 명령문을 사용하여 루프를 조기에 조기에 종료하는 솔루션은 Python 2.5.1을 사용하여 내 컴퓨터에서 약간 더 비싸다. 나는 이것이 반복 가능한 설정과 관련이 있다고 생각한다.

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

BTW : 일반 프로그램 흐름을 다음과 같은 것으로 재 작업하겠습니다.

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 또는 빈 문자열 인 경우 메소드가 잘못 반환됩니다.

이 버그를 내 자신의 코드로 너무 여러 번 만들었습니다!

관용 파이썬은 C 스타일의 3 차 운영자와 동등하지 않습니다

cond and true_expr or false_expr

즉.

list = get_list()
return list and list[0] or None
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top