2009-09-22 7 views
7

(제목과 알렉스의 대답 읽은 후 업데이트 된 내용) 일반적으로입력에 따라 iterable 또는 iterable이 아닌 함수를 반환하는 Pythonic입니까?

을 나는 그것이 때때로 반복 가능한 및 해당 매개 변수에 따라 때로는 단일 항목을 반환하는 기능에 나쁜 형태 (UN-파이썬) 간주 있다고 생각합니다.

예를 들어 struct.unpack은 하나의 항목 만 포함하는 경우에도 항상 튜플을 반환합니다.

나는 모듈에 대한 API를 마무리하기 위해 노력하고있어 나는 이런 (*args를 통해) 하나 개 이상의 매개 변수를 취할 수있는 몇 가지 기능이 :이 있다면

a = s.read(10)  # reads 10 bits and returns a single item 
b, c = s.read(5, 5) # reads 5 bits twice and returns a list of two items. 

따라서는 단일 항목을 반환합니다 하나의 매개 변수 만 그렇지 않으면 목록을 반환합니다. 이제는 이것이 잘되고 혼란스럽지 않다고 생각하지만, 다른 사람들이 동의하지 않을 수도 있습니다.

는 는 이 기능의 가장 일반적인 사용 사례는 그래서 항상 목록을 반환 (또는 튜플), 단일 항목을 반환하려는 경우에만하는 것입니다

잘못 느낌 :

a, = s.read(10)  # Prone to bugs when people forget to unpack the object 
a = s.read(10)[0]  # Ugly and it's not clear only one item is being returned 

또 다른 옵션은 두 가지 기능을하는 것입니다 :

a = s.read(10) 
b, c = s.read_list(5, 5) 
OK입니다

하지만 클러 위로 API를하고 어떤 가치를 추가하지 않고 두 배나 많은 기능을 기억하는 사용자가 필요합니다.

제 질문은 : 때로는 반복 가능하고 때로는 단일 항목이 혼란 스럽거나 피톤이 아닌 것을 반환합니까? 그렇다면 무엇이 최선의 선택입니까?


업데이트 : 나는 일반적인 합의는 단지 가끔 반복자를 반환에 매우 나쁜 있다고 생각합니다. 대부분의 경우 가장 좋은 옵션은 하나의 항목 만 포함되어 있어도 iterable을 항상 반환하는 것입니다.

내 특수한 경우에 대해 두 가지 기능 (read(item)/readlist(*items))으로 나눌 것이라고 생각합니다. 이유는 단일 항목의 경우가 여러 항목의 경우보다 훨씬 자주 발생한다고 생각합니다. 따라서 사용하기가 더 쉬워지고 API는 사용자에게 덜 문제가됩니다.

모두에게 감사드립니다. 파이썬 목록에서

답변

12

가끔 반복자를 반환 될 것하지 않으면, 당신은하지 않아도 다른 사람에 단일 객체, 나는 항상 반환 반복자 말하고 싶지만 그것에 대해 생각하기.

일반적으로 iterator가 필요한 컨텍스트에서이 함수를 사용하므로 반복 할 목록이나 작업을 한 번만 수행하면 개체를 확인해야 할 경우 iterator를 반환하고 한 번만 반복하더라도 항상 반복합니다.

하나의 요소가 반환 된 경우 다른 작업을 수행하려면 if len(var):을 사용하십시오.

일관성은 가치있는 것을 기억하십시오.

나는 일관된 객체가 아닌 necesarily 동일한 유형을 반환 향하다,하지만 난 이제까지 반복 가능한 돌아 오면, 나는 항상 반복 가능한 반환합니다. I 이렇게 것이다

+2

+1. 때로는 일이되고 때로는 일종의 목록이되는 것이 일반적으로 실수입니다. 파이썬은 % -formatting을 위해 이런 일을했는데, 이것은 널리 실수와 불쾌한 함정으로 간주됩니다. – bobince

+0

나는 사람들이 이것을 말할 까봐 두려웠다. 분명히 단 하나의 아이템에 대해서만 요구했을 때리스트를 얻는 것은 추한 것처럼 느껴졌다. –

+0

@Scot Griffiths : IMHO 간단한 변수가 초래할 수있는 문제를 너무 영리하게 외면함으로써 생기는 잠재적 인 버그. '* args'를 사용하는 대신 'def read (a_tuple) : '과 같은 메소드를 사용하지 않는 이유는 무엇입니까? – voyager

0

는 객체입니다 :) 그래서 어떤 유형이 일치하지

+0

True이면 충분합니다! 혼란을 피하기 위해 질문을 편집했습니다. –

1

유일한 상황은 발신자가 제공하는 하나 이상의 매개 변수는 리턴 타입을 결정하는 파라미터 함수 또는 메소드로이고; 개체의 논리적 비슷한 제품군 중 하나를 반환 예를 들어, "공장"기능 : 일반적인 경우

newCharacter = characterFactory("human", "male", "warrior") 

, 호출자가 지정하지 않습니다, 나는 초콜릿의 "상자를 피할 것 "행동. :)

+0

필자의 경우 리턴되는 아이템의 수는 함수 호출에서 주어진 아이템의 수와 같기 때문에 리턴 된 것에 놀라게 될 것이라고 나는 생각하지 않는다. –

2

일반적으로 두 가지 유형을 반환하는 것은 나쁜 습관이라고해야합니다.

다음 개발자가 코드를 읽고 유지 관리한다고 상상해보십시오. 처음에는 사용자는 함수를 사용하는 메소드를 읽고 "아, read()가 단일 항목을 반환합니다."라고 생각합니다.

나중에 read()의 결과를 목록으로 처리하는 코드가 표시됩니다. 기껏해야 이것들은 단지 그것들을 혼란스럽게 만들 것이고 read()의 사용법을 검토하도록 강요 할 것이다. 최악의 경우 그들은 read()를 사용하여 구현에 버그가 있다고 생각하고이를 수정하려고합니다. 그들이 스스로에게 물어해야합니다 반환) (두 가지 유형을 읽고, 이해하면

마지막으로, "아마도 내가 준비 할 필요가 세 번째 리턴 유형이?"

이이 말을 생각 나게 : ". 코드는 다음 사람이 코드는 당신이 살고있는 곳을 알고있는 살인 미치광이입니다 유지하는 경우로"

1

"파이썬"이 아닌 "좋은 디자인"의 문제 일 수 있습니다. 당신이 다른 것들을 returnd하면 누구도 아무도 그들에 typechecks을 할 수 없다, 그럼 아마 괜찮아요. 그것은 당신을위한 다형성입니다. OTOH, 발신자가 베일을 뚫어야한다면 Liskov Substitution Principle의 위반으로 알려진 디자인 문제가 있습니다. 파이 톤닉 (Pythonic) 이건 아니건간에, OO 디자인이 아니기 때문에 버그와 프로그래밍상의 불편 함이 발생하기 쉽습니다.

1

나는 (정수)와 read_list (반복 가능한)을 읽는 것입니다.

그런 식으로 당신이 (10)를 읽고 다시 하나의 결과와 read_list을받을 수 있나요 수 ([5, 5, 10, 5]) 다시 결과의 목록을 얻을. 이는보다 유연하고 명확합니다.

2

은 단일 객체 또는 객체의 반복 가능한 중 하나를 반환, 인수에 따라 처리 할 확실히 어렵다. 그러나 제목에 나오는 질문은 훨씬 더 일반적이며 표준 라이브러리의 함수가 인수를 기반으로 다른 유형을 반환하는 것을 피하는 (또는 "대부분 피하는") 주장은 상당히 잘못된 것입니다. 많은 반대 사례가 있습니다.

함수 copy.copycopy.deepcopy은 인수와 동일한 형식을 반환하므로 물론 인수에 따라 다른 형식을 반환합니다. "입력과 동일한 유형의 반환"은 실제로 매우 일반적입니다. 여기서는 클래스를 추가 할 수도 있고, 컨테이너에 객체를 넣을 수도 있습니다. 일반적으로 함수가 아닌 메소드로 완료되었지만 ;-) . 뿐만 아니라, 같은 맥락에서, ... filter, 말, (당신은 그것의 반환 반복자에 반복되면) itertools.repeat을 고려, 또는 :

>>> filter(lambda x: x>'f', 'zaplepidop') 
'zplpiop' 
>>> filter(lambda x: x>'f', list('zaplepidop')) 
['z', 'p', 'l', 'p', 'i', 'o', 'p'] 

문자열을 필터링하여 목록을 필터링하는 목록을 반환 문자열을 반환합니다.) pickle.loads을 기능과 그 친구 (예를 들어, 모듈의 인수로 전달하는 가치에 전적으로 의존 유형 marshal & c) 반환 개체 -!

은 그러나 잠깐, 거기에 더 많은입니다. 그래서 내장 함수 eval (그리고 비슷하게 input, 파이썬 2. *에서). 이것은 두 번째로 일반적인 패턴입니다. 인수의 값에 따라 객체를 구성하거나 재구성 할 수 있으며 가능한 다양한 유형의 다양한 객체를 반환하고 반환 할 수 있습니다.

내가 본 특정 안티 패턴에 대한 좋은 예는 알지 못합니다. (그리고 나는 그것이 안티 패턴이라고 생각합니다. 약간의 이유는 아닙니다. 단지 성가시고 처리하기가 불편하기 때문입니다. 와;-). 제가 예시 한 이러한 사례는 편리하고 편리합니다 - 대부분의 표준 라이브러리 문제에서 실제 디자인 판별 자입니다 -)

+0

당신은 질문이 너무 일반적으로 표현된다는 것이 맞습니다. 그리고 그것은 정말로 인터럽트 대 비 인터럽트 문제로 귀결됩니다. 당신이 그것을 반 패턴이라고 부른다면 그것은 죽음을 알 수 있습니다. -) –

관련 문제