[python] 빈 목록 인 기본 매개 변수를 피하는 파이썬적인 방법은 무엇입니까?

때로는 빈 목록 인 기본 매개 변수를 갖는 것이 자연스러워 보입니다. 그러나 파이썬은 이러한 상황에서 예기치 않은 동작을 제공합니다 .

예를 들어, 기능이 있습니다.

def my_func(working_list = []):
    working_list.append("a")
    print(working_list)

처음 호출하면 기본값이 작동하지만 그 이후의 호출은 기존 목록을 업데이트하고 (각 호출마다 하나의 “a”포함) 업데이트 된 버전을 인쇄합니다.

그래서, 내가 원하는 행동을 얻는 비단 법적인 방법은 무엇입니까 (각 호출에 대한 새로운 목록)?



답변

def my_func(working_list=None):
    if working_list is None:
        working_list = []

    working_list.append("a")
    print(working_list)

문서None 에서는 기본값으로 사용 하고 함수 본문에서 명시 적으로 테스트 해야한다고 말합니다 .


답변

기존 답변은 이미 요청한 직접적인 솔루션을 제공했습니다. 그러나 이것은 새로운 Python 프로그래머에게 매우 일반적인 함정이므로 Python이 이러한 방식으로 작동하는 이유에 대한 설명을 추가 할 가치가 있습니다. 이는 ” The Hitchhikers Guide to Python “에 ” Mutable Default Arguments ” 로 잘 요약되어 있습니다 .
http : // docs .python-guide.org / en / latest / writing / gotchas /

인용구 : ” Python의 기본 인수는 함수가 호출 될 때마다가 아니라 함수가 정의 될 때 한 번 평가됩니다 (예 : Ruby). 즉, 변경 가능한 기본 인수를 사용하고 변경하면 함수에 대한 모든 향후 호출에 대해서도 해당 개체를 변경했습니다.

이를 구현하기위한 샘플 코드 :

def foo(element, to=None):
    if to is None:
        to = []
    to.append(element)
    return to


답변

이 경우 중요하지는 않지만 객체 ID를 사용하여 None을 테스트 할 수 있습니다.

if working_list is None: working_list = []

부울 연산자 또는 파이썬에서 정의되는 방법을 활용할 수도 있습니다.

working_list = working_list or []

호출자가 working_list로 빈 목록 (거짓으로 계산 됨)을 제공하고 함수가 그가 제공 한 목록을 수정하기를 기대하는 경우 예기치 않게 작동하지만.


답변

함수의 의도가로 전달 된 매개 변수 를 수정 하는 working_list것이라면 HenryR의 답변을 참조하십시오 (= None, 내부 없음 확인).

그러나 인수를 변경하지 않으려는 경우 목록의 시작점으로 사용하고 간단히 복사 할 수 있습니다.

def myFunc(starting_list = []):
    starting_list = list(starting_list)
    starting_list.append("a")
    print starting_list

(또는이 간단한 경우에는 그냥 print starting_list + ["a"]장난감 예제 일 뿐이라고 생각합니다)

일반적으로 인수를 변경하는 것은 Python에서 나쁜 스타일입니다. 객체를 완전히 변형시킬 것으로 예상되는 유일한 함수는 객체의 메서드입니다. 선택적 인수를 변경하는 것은 더욱 드뭅니다. 일부 호출에서만 발생하는 부작용이 정말 최상의 인터페이스입니까?

  • “출력 인수”라는 C 습관에서 수행하면 완전히 불필요합니다. 항상 여러 값을 튜플로 반환 할 수 있습니다.

  • 중간 목록을 작성하지 않고 긴 결과 목록을 효율적으로 작성하기 위해 이렇게하면 생성기로 작성하고 result_list.extend(myFunc())호출 할 때 사용 하는 것이 좋습니다. 이렇게하면 호출 규칙이 매우 깨끗하게 유지됩니다.

옵션 인수가 돌연변이 한 패턴 입니다 자주 수행은 재귀 함수의 숨겨진 “메모”인수입니다 :

def depth_first_walk_graph(graph, node, _visited=None):
    if _visited is None:
        _visited = set()  # create memo once in top-level call

    if node in _visited:
        return
    _visited.add(node)
    for neighbour in graph[node]:
        depth_first_walk_graph(graph, neighbour, _visited)


답변

주제에서 벗어 났을 수도 있지만 가변 개수의 인수 만 전달하려는 경우 비단뱀적인 방법은 튜플 *args또는 사전 을 전달하는 것 **kargs입니다. 이는 선택 사항이며 구문보다 낫습니다 myFunc([1, 2, 3]).

튜플을 전달하려면 :

def myFunc(arg1, *args):
  print args
  w = []
  w += args
  print w
>>>myFunc(1, 2, 3, 4, 5, 6, 7)
(2, 3, 4, 5, 6, 7)
[2, 3, 4, 5, 6, 7]

사전을 전달하려면 :

def myFunc(arg1, **kargs):
   print kargs
>>>myFunc(1, option1=2, option2=3)
{'option2' : 2, 'option1' : 3}


답변

이미 훌륭하고 정답이 제공되었습니다. 예를 들어 기본 빈 목록으로 클래스를 만들고 싶을 때 더 아름답다고 생각하는 작업을 작성하기 위해 다른 구문을 제공하고 싶었습니다.

class Node(object):
    def __init__(self, _id, val, parents=None, children=None):
        self.id = _id
        self.val = val
        self.parents = parents if parents is not None else []
        self.children = children if children is not None else []

이 스 니펫은 if else 연산자 구문을 사용합니다. 특히 콜론 등이없는 깔끔한 한 줄짜리이고 거의 일반 영어 문장처럼 읽기 때문에 특히 좋습니다. 🙂

귀하의 경우에는 쓸 수 있습니다

def myFunc(working_list=None):
    working_list = [] if working_list is None else working_list
    working_list.append("a")
    print working_list


답변

UCSC 확장 수업을 들었습니다. Python for programmer

def Fn (data = []) :

a) 호출 할 때마다 데이터 목록이 비어 있도록하는 것이 좋습니다.

b)는 호출에서 인수를 제공하지 않는 함수에 대한 모든 호출이 데이터로 빈 목록을 가져 오도록하는 좋은 생각입니다.

c) 데이터가 문자열 목록 인 한 합리적인 아이디어입니다.

d)는 기본 []이 데이터를 축적하고 기본 []이 후속 호출로 변경되기 때문에 나쁜 생각입니다.

대답:

d)는 기본 []이 데이터를 축적하고 기본 []이 후속 호출로 변경되기 때문에 나쁜 생각입니다.