본문 바로가기

파이썬 튜토리얼 / Pythonチュートリアル 4. 기타 제어 흐름 도구 その他の制御フローツール

https://docs.python.org/ko/3/tutorial/controlflow.html#default-argument-values


4. 기타 제어 흐름 도구

4. その他の制御フローツール


방금 소개한 while 문 외에도, 파이썬은 다른 언어들에서 알려진 일반적인 제어 흐름 문들을 알고 있으며, 

나름의 변형을 가하고 있습니다.


先ほど紹介した while 文の他にも、 Python は他の言語でおなじみの制御フロー文を備えていますが、

これらには多少ひねりを加えてあります。



4.1. if 문

4.1. if 文



아마도 가장 잘 알려진 문장 형은 if 문일 것입니다. 예를 들어:

おそらく最もおなじみの文型は if 文でしょう。例えば:

>>>
>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
...     x = 0
...     print('Negative changed to zero')
... elif x == 0:
...     print('Zero')
... elif x == 1:
...     print('Single')
... else:
...     print('More')
...
More

없거나 여러 개의 elif 부가 있을 수 있고, else 부는 선택적입니다. 

키워드 'elif' 는 'else if' 의 줄임 표현인데, 과도한 들여쓰기를 피하는 데 유용합니다.

if ... elif ... elif ... 시퀀스는 다른 언어들에서 발견되는 switch 나 case 문을 대신합니다.


ゼロ個以上の elif 部を使うことができ、 else 部を付けることもできます。

キーワード 'elif' は 'else if' を短くしたもので、過剰なインデントを避けるのに役立ちます。

一連の if ... elif ... elif ... は、他の言語における switch 文や case 文の代用となります。


4.2. for 문

4.2. for 文


파이썬에서 for 문은 C 나 파스칼에서 사용하던 것과 약간 다릅니다. 

(파스칼처럼) 항상 숫자의 산술적인 진행을 통해 이터레이션 하거나, (C처럼) 사용자가 이터레이션 단계와 중지 조건을 정의할 수 있도록 하는 대신, 파이썬의 for 문은 임의의 시퀀스 (리스트나 문자열)의 항목들을 그 시퀀스에 들어있는 순서대로 이터레이션 합니다. 

예를 들어 (말장난이 아니라):


Python の for 文は、読者が C 言語や Pascal 言語で使いなれているかもしれない for 文とは少し違います。 

(Pascal のように) 常に算術型の数列にわたる反復を行ったり、 (C のように) 繰返しステップと停止条件を両方ともユーザが定義できるようにするのとは違い、Python の for 文は、任意のシーケンス型 (リストまたは文字列) にわたって反復を行います。反復の順番はシーケンス中に要素が現れる順番です。

例えば:

>>>
>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
...     print(w, len(w))
...
cat 3
window 6
defenestrate 12

루프 안에서 이터레이트하는 시퀀스를 수정할 필요가 있다면 (예를 들어, 선택한 항목들을 중복시키기), 먼저 사본을 만들 것을 권합니다. 시퀀스를 이터레이트할 때 묵시적으로 사본이 만들어지지는 않습니다. 슬라이스 표기법은 이럴 때 특히 편리합니다:

ループ内部でイテレートしているシーケンスを修正する必要があれば (例えば選択されたアイテムを複製するために)、最初にコピーを作ることをお勧めします。シーケンスに対するイテレーションは暗黙にコピーを作りません。スライス記法はこれを特に便利にします:

>>>
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

for w in words: 를 쓰면, 위의 예는 defenestrate 를 반복해서 넣고 또 넣음으로써, 무한한 리스트를 만들려고 시도하게 됩니다.

for w in words: を使った場合は、この例は defenestrate を何度も繰り返し挿入することで、無限リストを作成しようとします。


4.3. range() 함수

4.3. range() 関数


숫자들의 시퀀스로 이터레이트할 필요가 있으면, 내장 함수 range() 가 편리합니다. 수열을 만듭니다:

数列にわたって反復を行う必要がある場合、組み込み関数 range() が便利です。この関数は算術型の数列を生成します:

>>>
>>> for i in range(5):
...     print(i)
...
0
1
2
3
4

끝값은 만들어지는 수열에 포함되지 않습니다; range(10) 은 10개의 값을 만드는데, 길이 10인 시퀀스의 항목들을 가리키는 올바른 인덱스들입니다. 범위가 다른 숫자로 시작하거나, 다른 증가분을 (음수조차 가능합니다; 때로 이것을 '스텝(step)'이라고 부릅니다) 지정하는 것도 가능합니다:


指定した終端値は生成されるシーケンスには入りません。range(10) は 10 個の値を生成し、長さ 10 のシーケンスにおける各項目のインデクスとなります。range を別の数から開始したり、他の増加量 (負でも; 増加量は時に 'ステップ(step)' と呼ばれることもあります) を指定することもできます:



range(5, 10)
   5, 6, 7, 8, 9

range(0, 10, 3)
   0, 3, 6, 9

range(-10, -100, -30)
  -10, -40, -70

시퀀스의 인덱스들로 이터레이트 하려면, 다음처럼 range() 와 len() 을 결합할 수 있습니다:

あるシーケンスにわたってインデクスで反復を行うには、 range() と len() を次のように組み合わせられます:


>>>
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
...     print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb

하지만, 그럴 때 대부분은, enumerate() 함수를 쓰는 것이 편리합니다, 루프 테크닉 를 보세요.

범위를 그냥 인쇄하면 이상한 일이 일어납니다:


しかし、多くの場合は enumerate() 関数を使う方が便利です。 ループのテクニック を参照してください。

range を直接出力すると変なことになります:


>>>
>>> print(range(10))
range(0, 10)

많은 경우에 range() 가 돌려준 객체는 리스트인 것처럼 동작하지만, 사실 리스트가 아닙니다. 이터레이트할 때 원하는 시퀀스 항목들을 순서대로 돌려주는 객체이지만, 실제로 리스트를 만들지 않아서 공간을 절약합니다.


range() が返すオブジェクトは、いろいろな点でリストであるかのように振る舞いますが、本当はリストではありません。これは、イテレートした時に望んだ数列の連続した要素を返すオブジェクトです。しかし実際にリストを作るわけではないので、スペースの節約になります。



이런 객체를 이터러블 이라고 부릅니다. 공급이 소진될 때까지 일련의 항목들을 얻을 수 있는 무엇인가를 기대하는 함수와 구조물들의 타깃으로 적합합니다. 우리는 for 문이 그런 구조물임을 보았습니다. 함수 list() 도 그런 것입니다; 이터러블로 리스트를 만듭니다:


このようなオブジェクトは イテラブル (iterable) と呼ばれます。これらは関数やコンストラクタのターゲットとして、あるだけの項目を逐次与えるのに適しています。 for 文がそのような イテレータ であることはすでに見てきました。関数 list() もまた一つの例です。これはイテラブルからリストを生成します:



>>>
>>> list(range(5))
[0, 1, 2, 3, 4]

나중에 이터러블을 돌려주고 이터러블을 인자로 받는 함수들을 더 보게 됩니다.

後ほど、イテラブルを返したりイテラブルを引数として取る関数をもっと見ていきます。


4.4. 루프의 break 와 continue 문, 그리고 else 절

4.4. break 文と continue 文とループの else 節


break 문은, C처럼, 가장 가까이서 둘러싸는 for 나 while 루프로부터 빠져나가게 만듭니다.

break 文は、C 言語と同じく、最も内側の for または while ループを中断します。


루프 문은 else 절을 가질 수 있습니다; 루프가 리스트의 소진이나 (for 의 경우) 조건이 거짓이 돼서 (while 의 경우) 종료할 때 실행됩니다. 

하지만 루프가 break 문으로 종료할 때는 실행되지 않습니다. 


소수를 찾는 루프를 통해 다음에서 예시합니다:


ループ文は else 節を持つことができます。これは、 (for で) 反復処理対象のリストを使い切ってループが終了したとき、または (while で) 条件が偽になったときに実行されますが、

 break 文でループが終了したときは実行されません。この動作を、


素数を探す下記のループを例にとって示します:



>>>
>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(이것은 올바른 코드입니다. 자세히 들여다보면: else 절은 if문이 아니라 for 루프에 속합니다.)

(そう、これは正しいコードです。よく見てください: else 節は if 文 ではなく 、 for ループに属しています。)


루프와 함께 사용될 때, else 절은 if 문보다는 try 문의 else 절과 비슷한 면이 많습니다: try 문의 else 절은 예외가 발생하지 않을 때 실행되고, 루프의 else 절은 break 가 발생하지 않을 때 실행됩니다. try 문과 예외에 관한 자세한 내용은 예외 처리하기를 보세요.


ループの else 句は、 if 文の else よりも try 文の else に似ています。 try 文の else 句は例外が発生しなかった時に実行され、ループの else 句は break されなかった場合に実行されます。 try 文と例外についての詳細は 例外を処理する を参照してください。


continue 문은, 역시 C에서 빌렸습니다, 루프의 다음 이터레이션에서 계속하도록 만듭니다:

continue 文も C 言語から借りてきたもので、ループの次のイテレーションを実行します:


>>>
>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9

4.5. pass 문

4.5. pass 文


pass 문은 아무것도 하지 않습니다. 

문법적으로 문장이 필요하지만, 프로그램이 특별히 할 일이 없을 때 사용할 수 있습니다. 예를 들어:


pass 文は何もしません。

 pass は、文を書くことが構文上要求されているが、プログラム上何の動作もする必要がない時に使われます:

>>>
>>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...

최소한의 클래스를 만들 때 흔히 사용된다:

これは最小のクラスを作るときによく使われる方法です:


>>>
>>> class MyEmptyClass:
...     pass
...

pass 가 사용될 수 있는 다른 장소는 새 코드를 작업할 때 함수나 조건부 바디의 자리를 채우는 것인데, 여러분이 더 추상적인 수준에서 생각할 수 있게 합니다. pass 는 조용히 무시됩니다:


pass のもう 1 つの使い道は、新しいコードを書いているときの関数や条件文の仮置きの本体としてです。こうすることで、より抽象的なレベルで考え続けられます。 pass は何事も無く無視されます


>>>
>>> def initlog(*args):
...     pass   # Remember to implement this!
...

4.6. 함수 정의하기

4.6. 関数を定義する


피보나치 수열을 임의의 한도까지 출력하는 함수를 만들 수 있습니다:

フィボナッチ数列 (Fibonacci series) を任意の上限値まで書き出すような関数を作成できます:

>>>
>>> def fib(n):    # write Fibonacci series up to n
...     """Print a Fibonacci series up to n."""
...     a, b = 0, 1
...     while a < n:
...         print(a, end=' ')
...         a, b = b, a+b
...     print()
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

키워드 def 는 함수 정의 를 시작합니다. 함수 이름과 괄호로 싸인 형식 매개변수들의 목록이 뒤따릅니다. 함수의 바디를 형성하는 문장들이 다음 줄에서 시작되고, 반드시 들여쓰기 되어야 합니다.


def は関数の 定義 (definition) を導くキーワードです。 def の後には、関数名と仮引数を丸括弧で囲んだリストを続けなければなりません。関数の実体を構成する実行文は次の行から始め、インデントされていなければなりません。



함수 바디의 첫 번째 문장은 선택적으로 문자열 리터럴이 될 수 있습니다; 이 문자열 리터럴은 함수의 토큐멘테이션 문자열, 즉 독스트링 (docstring) 입니다. (독스트링에 대한 자세한 내용은 도큐멘테이션 문자열 에 나옵니다.) 독스트링을 사용해서 온라인이나 인쇄된 설명서를 자동 생성하거나, 사용자들이 대화형으로 코드를 열람할 수 있도록 하는 도구들이 있습니다; 여러분이 작성하는 코드에 독스트링을 첨부하는 것은 좋은 관습입니다, 그러니 버릇을 들이는 것이 좋습니다.


関数の本体の記述する文の最初の行は文字列リテラルにすることもできます。その場合、この文字列は関数のドキュメンテーション文字列 (documentation string)、または docstring と呼ばれます。 (docstring については ドキュメンテーション文字列でさらに扱っています。) ドキュメンテーション文字列を使ったツールには、オンライン文書や印刷文書を自動的に生成したり、ユーザが対話的にコードから直接閲覧できるようにするものがあります。自分が書くコードにドキュメンテーション文字列を入れるのはよい習慣です。書く癖をつけてください。




함수의 실행 은 함수의 지역 변수들을 위한 새 심볼 테이블을 만듭니다. 좀 더 구체적으로, 함수에서의 모든 변수 대입들은 값을 지역 심볼 테이블에 저장합니다; 반면에 변수 참조는 먼저 지역 심볼 테이블을 본 다음, 전역 심볼 테이블을 본 후, 마지막으로 내장 이름들의 테이블을 살핍니다. 그래서, 참조될 수는 있다 하더라도, 전역 변수들은 함수 내에서 (global 문으로 명시하지 않는 이상) 직접 값이 대입될 수 없습니다.


関数を 実行 (execution) するとき、関数のローカル変数のために使われる新たなシンボルテーブル (symbol table) が用意されます。もっと正確にいうと、関数内で変数への代入を行うと、その値はすべてこのローカルなシンボルテーブルに記憶されます。一方、変数の参照を行うと、まずローカルなシンボルテーブルが検索され、次にさらに外側の関数のローカルなシンボルテーブルを検索し、その後グローバルなシンボルテーブルを調べ、最後に組み込みの名前テーブルを調べます。従って、関数の中では、グローバルな変数を参照することはできますが、直接値を代入することは (global 文で名前を挙げておかない限り)できません。



함수 호출로 전달되는 실제 매개변수들 (인자들)은 호출될 때 호출되는 함수의 지역 심볼 테이블에 만들어집니다; 그래서 인자들은 값에 의한 호출 (call by value) 로 전달됩니다 ( 은 항상 객체의 값이 아니라 객체 참조 입니다). [1] 함수가 다른 함수를 호출할 때, 그 호출을 위한 새 지역 심볼 테이블이 만들어집니다.


関数を呼び出す際の実際の引数 (実引数) は、関数が呼び出されるときに関数のローカルなシンボルテーブル内に取り込まれます。そうすることで、引数は 値渡し (call by value) で関数に渡されることになります (ここでの 値 (value) とは常にオブジェクトへの 参照(reference) をいい、オブジェクトの値そのものではありません) [1]。ある関数がほかの関数を呼び出すときには、新たな呼び出しのためにローカルなシンボルテーブルが新たに作成されます。



함수 정의는 현재 심볼 테이블에 함수 이름을 만듭니다. 함수 이름의 값은 인터프리터가 사용자 정의 함수로 인식하는 형입니다. 이 값은 다른 이름에 대입될 수 있는데, 이 역시 함수로 사용될 수 있습니다. 이것이 이름을 바꾸는 일반적인 방법입니다:


関数の定義を行うと、関数名は現在のシンボルテーブル内に取り入れられます。関数名の値は、インタプリタからはユーザ定義関数 (user-defined function) として認識される型を持ちます。この値は別の名前に代入して、後にその名前を関数として使うこともできます。これは一般的な名前変更のメカニズムとして働きます:


>>>
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

다른 언어들을 사용했다면, fib 가 값을 돌려주지 않기 때문에 함수가 아니라 프로시저라고 생각할 수 있습니다. 

사실, return문이 없는 함수도 값을 돌려줍니다, 비록 따분한 값이기는 하지만. 이 값은 None 이라고 불립니다 (내장 이름입니다). None 이 출력할 유일한 값이라면, 인터프리터는 보통 None 값 출력을 억제합니다. 꼭 보길 원한다면 print() 를 사용할 수 있습니다:


他の言語出身の人からは、 fib は値を返さないので関数ではなく手続き (procedure) だと異論があるかもしれませんね。技術的に言えば、実際には return 文を持たない関数もややつまらない値ですが値を返しています。この値は None と呼ばれます (これは組み込みの名前です)。 None だけを書き出そうとすると、インタプリタは通常出力を抑制します。本当に出力したいのなら、以下のように print() を使うと見ることができます:



>>>
>>> fib(0)
>>> print(fib(0))
None

인쇄하는 대신, 피보나치 수열의 숫자들 리스트를 돌려주는 함수를 작성하는 것도 간단합니다:

フィボナッチ数列の数からなるリストを出力する代わりに、値を返すような関数を書くのは簡単です:

>>>
>>> def fib2(n):  # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

여느 때처럼, 이 예는 몇 가지 새 파이썬 기능을 보여줍니다:

    この例は Python の新しい機能を示しています:

    • return 문은 함수로부터 값을 갖고 복귀하게 만듭니다. 표현식 인자 없는 return 은 None 을 돌려줍니다. 함수의 끝으로 떨어지면 역시 None 을 돌려줍니다.
    • 문장 result.append(a) 은 리스트 객체 result 의 메서드를 호출합니다. 메서드는 객체에 '속하는' 함수이고 obj.methodname 라고 이름 붙여지는데, obj 는 어떤 객체이고 (표현식이 될 수 있습니다), methodname 는 객체의 형에 의해 정의된 메서드의 이름입니다. 다른 형은 다른 메서드들을 정의합니다. 서로 다른 형들의 메서드는 모호함 없이 같은 이름을 가질 수 있습니다. (클래스 를 사용해서 여러분 자신의 형과 메서드를 정의하는 것이 가능합니다, 클래스 를 보세요) 예에 나오는 메서드 append() 는 리스트 객체들에 정의되어 있습니다; 요소를 리스트의 끝에 덧붙입니다. 이 예에서는 result = result + [a] 와 동등하지만, 더 효율적입니다.

    • return 文では、関数から一つ値を返します。 return の引数となる式がない場合、 None が返ります。関数が終了したときにも None が返ります。
    • 文 result.append(a) では、リストオブジェクト result の メソッド (method)を呼び出しています。メソッドとは、オブジェクトに '属している' 関数のことで、 obj を何らかのオブジェクト (式であっても構いません)、 methodname をそのオブジェクトで定義されているメソッド名とすると、 obj.methodname と書き表されます。異なる型は異なるメソッドを定義しています。異なる型のメソッドで同じ名前のメソッドを持つことができ、あいまいさを生じることはありません。 (クラス (class) を使うことで、自前のオブジェクト型とメソッドを定義することもできます。 クラス 参照) 例で示されているメソッド append()は、リストオブジェクトで定義されています; このメソッドはリストの末尾に新たな要素を追加します。この例での append() は result = result + [a] と等価ですが、より効率的です。


    4.7. 함수 정의 더 보기

    4.7. 関数定義についてもう少し


    정해지지 않은 개수의 인자들로 함수를 정의하는 것도 가능합니다. 세 가지 형식이 있는데, 조합할 수 있습니다.


    可変個の引数を伴う関数を定義することもできます。

    引数の定義方法には 3 つの形式があり、それらを組み合わせることができます。


    4.7.1. 기본 인자 값

    4.7.1. デフォルトの引数値


    가장 쓸모 있는 형식은 하나나 그 이상 인자들의 기본값을 지정하는 것입니다. 정의된 것보다 더 적은 개수의 인자들로 호출될 수 있는 함수를 만듭니다. 예를 들어:

    もっとも便利なのは、一つ以上の引数に対してデフォルトの値を指定する形式です。この形式を使うと、定義されている引数より少ない個数の引数で呼び出せる関数を作成します:


    def ask_ok(prompt, retries=4, reminder='Please try again!'):
        while True:
            ok = input(prompt)
            if ok in ('y', 'ye', 'yes'):
                return True
            if ok in ('n', 'no', 'nop', 'nope'):
                return False
            retries = retries - 1
            if retries < 0:
                raise ValueError('invalid user response')
            print(reminder)
    

    이 함수는 여러 가지 방법으로 호출될 수 있습니다:

    • 오직 꼭 필요한 인자만 전달해서: ask_ok('정말 끝내길 원하세요?')
    • 선택적 인자 하나를 제공해서: ask_ok('파일을 덮어써도좋습니까?', 2)
    • 또는 모든 인자를 제공해서: ask_ok('파일을 덮어써도 좋습니까?', 2, '자, 예나 아니요로만 답하세요!')


    この関数はいくつかの方法で呼び出せます:

    • 必須の引数のみ与える: ask_ok('Do you really want to quit?')
    • 一つのオプション引数を与える: ask_ok('OK to overwrite the file?', 2)
    • 全ての引数を与える: ask_ok('OK to overwrite the file?', 2, 'Come on, onlyyes or no!')


    이 예는 in 키워드도 소개하고 있습니다. 시퀀스가 어떤 값을 가졌는지 아닌지를 검사합니다.

    この例では in キーワードが導入されています。このキーワードはシーケンスが特定の値を含んでいるかどうか調べるのに使われます。


    기본값은 함수 정의 시점에 정의되고 있는 스코프에서 구해집니다, 그래서

    デフォルト値は、関数が定義された時点で、関数を 定義している 側のスコープ (scope) で評価されるので

    i = 5
    
    def f(arg=i):
        print(arg)
    
    i = 6
    f()
    

    는 5 를 인쇄한다.

    は 5 を出力します。



    중요한 주의사항: 기본값은 오직 한 번만 값이 구해집니다. 이것은 기본값이 리스트나 딕셔너리나 대부분 클래스의 인스턴스와 같은 가변 객체일 때 차이를 만듭니다. 예를 들어, 다음 함수는 계속되는 호출로 전달된 인자들을 누적합니다:


    重要な警告: デフォルト値は 1 度だけしか評価されません。デフォルト値がリストや辞書のような変更可能なオブジェクトの時にはその影響がでます。例えば以下の関数は、後に続く関数呼び出しで関数に渡されている引数を累積します:

    def f(a, L=[]):
        L.append(a)
        return L
    
    print(f(1))
    print(f(2))
    print(f(3))
    

    다음과 같은 것을 인쇄합니다.

    このコードは、以下を出力します

    [1]
    [1, 2]
    [1, 2, 3]
    

    연속된 호출 간에 기본값이 공유되지 않기를 원한다면, 대신 함수를 이런 식으로 쓸 수 있습니다:

    後続の関数呼び出しでデフォルト値を共有したくなければ、代わりに以下のように関数を書くことができます:

    def f(a, L=None):
        if L is None:
            L = []
        L.append(a)
        return L
    

    4.7.2. 키워드 인자

    4.7.2. キーワード引数


    함수는 kwarg=value 형식의 키워드 인자 를 사용해서 호출될 수 있습니다. 예를 들어, 다음 함수는:

    関数を kwarg=value という形式の キーワード引数 を使って呼び出すこともできます。例えば、以下の関数:


    def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
        print("-- This parrot wouldn't", action, end=' ')
        print("if you put", voltage, "volts through it.")
        print("-- Lovely plumage, the", type)
        print("-- It's", state, "!")
    

    하나의 필수 인자 (voltage) 와 세 개의 선택적 인자 (stateactiontype) 를 받아들입니다. 이 함수는 다음과 같은 방법 중 아무것으로나 호출될 수 있습니다.

    は、必須引数 (voltage) とオプション引数 (stateactiontype) を受け付けます。この関数は以下のいずれかの方法で呼び出せます:

    parrot(1000)                                          # 1 positional argument
    parrot(voltage=1000)                                  # 1 keyword argument
    parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
    parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
    parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
    parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword
    

    하지만 다음과 같은 호출들은 모두 올바르지 않습니다:

    が、以下の呼び出しは不適切です:

    parrot()                     # required argument missing
    parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
    parrot(110, voltage=220)     # duplicate value for the same argument
    parrot(actor='John Cleese')  # unknown keyword argument
    

    함수 호출에서, 키워드 인자는 위치 인자 뒤에 나와야 합니다. 전달된 모든 키워드 인자는 함수가 받아들이는 인자 중 하나와 맞아야 하며 (예를 들어, actor 는 parrot 함수의 올바른 인자가 아니다), 그 순서는 중요하지 않습니다. 이것들에는 필수 인자들도 포함됩니다 (예를 들어, parrot(voltage=1000) 도 올바릅니다). 어떤 인자도 두 개 이상의 값을 받을 수 없습니다. 여기, 이 제약 때문에 실패하는 예가 있습니다:


    関数の呼び出しにおいて、キーワード引数は位置引数の後でなければなりません。渡されるキーワード引数は全て、関数で受け付けられる引数のいずれかに対応していなければならず (例えば、actor はこの parrot 関数の引数として適切ではありません)、順序は重要ではありません。これはオプションでない引数でも同様です (例えば、parrot(voltage=1000) も適切です)。いかなる引数も値を複数回は受け取れません。この制限により失敗する例は:


    >>>
    >>> def function(a):
    ...     pass
    ...
    >>> function(0, a=0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: function() got multiple values for keyword argument 'a'
    

    **name 형식의 마지막 형식 매개변수가 존재하면, 형식 매개변수들에 대응하지 않는 모든 키워드 인자들을 담은 딕셔너리 (매핑 형 --- dict 를 보세요) 를 받습니다. 


    이것은 *name (다음 서브섹션에서 설명한다) 형식의 형식 매개변수와 조합될 수 있는데, 형식 매개변수 목록 밖의 위치 인자들을 담은 튜플을 받습니다. (*name 은 **name 앞에 나와야 합니다.) 예를 들어, 이런 함수를 정의하면:


    仮引数の最後に **name の形式のものがあると、それまでの仮引数に対応したものを除くすべてのキーワード引数が入った辞書 (マッピング型 --- dict を参照) を受け取ります。


     **name は *name の形式をとる、仮引数のリストを超えた位置引数の入ったタプルを受け取る引数 (次の節で述べます) と組み合わせることができます。 (*name は **name より前になければなりません)。例えば、ある関数の定義を以下のようにすると:

    def cheeseshop(kind, *arguments, **keywords):
        print("-- Do you have any", kind, "?")
        print("-- I'm sorry, we're all out of", kind)
        for arg in arguments:
            print(arg)
        print("-" * 40)
        for kw in keywords:
            print(kw, ":", keywords[kw])
    

    이런 식으로 호출될 수 있습니다:

    呼び出しは以下のようになり:

    cheeseshop("Limburger", "It's very runny, sir.",
               "It's really very, VERY runny, sir.",
               shopkeeper="Michael Palin",
               client="John Cleese",
               sketch="Cheese Shop Sketch")
    

    그리고 당연히 이렇게 인쇄합니다:

    もちろん以下のように出力されます:

    -- Do you have any Limburger ?
    -- I'm sorry, we're all out of Limburger
    It's very runny, sir.
    It's really very, VERY runny, sir.
    ----------------------------------------
    shopkeeper : Michael Palin
    client : John Cleese
    sketch : Cheese Shop Sketch
    

    인쇄되는 키워드 인자들의 순서 함수 호출로 전달된 순서와 일치함이 보장됨에 주목하세요.

    なお、複数のキーワード引数を与えた場合に、それらが出力される順序は、関数呼び出しで与えられた順序と同じになります。


    4.7.3. 임의의 인자 목록

    4.7.3. 任意引数リスト


    마지막으로, 가장 덜 사용되는 옵션은 함수가 임의의 개수 인자로 호출될 수 있도록 지정하는 것입니다. 이 인자들은 튜플로 묶입니다 (튜플과 시퀀스 을 보세요). 가변 길이 인자 앞에, 없거나 여러 개의 일반 인자들이 올 수 있습니다.


    最後に、最も使うことの少ない選択肢として、関数が任意の個数の引数で呼び出せるよう指定する方法があります。これらの引数はタプル (タプルとシーケンス を参照) に格納されます。可変個の引数の前に、ゼロ個かそれ以上の引数があっても構いません。


    def write_multiple_items(file, separator, *args):
        file.write(separator.join(args))
    

    보통, 이 가변 길이 인자들은 형식 매개변수 목록의 마지막에 옵니다, 함수로 전달된 남은 입력 인자들 전부를 그러모으기 때문입니다. *args 매개변수 뒤에 등장하는 형식 매개변수들은 모두 '키워드-전용' 인자들인데, 위치 인자 대신 키워드 인자로만 사용될 수 있다는 뜻입니다.


    通常このような 可変 引数は、関数に渡される入力引数の残りを全て掬い取るために、仮引数リストの最後に置かれます。*args 引数の後にある仮引数は 'キーワード専用' 引数で、位置引数ではなくキーワード引数としてのみ使えます。


    >>>
    >>> def concat(*args, sep="/"):
    ...     return sep.join(args)
    ...
    >>> concat("earth", "mars", "venus")
    'earth/mars/venus'
    >>> concat("earth", "mars", "venus", sep=".")
    'earth.mars.venus'
    

    4.7.4. 인자 목록 언 패킹

    4.7.4. 引数リストのアンパック


    인자들이 이미 리스트나 튜플에 있지만, 분리된 위치 인자들을 요구하는 함수 호출을 위해 언 패킹 해야 하는 경우 반대 상황이 벌어집니다. 예를 들어, 내장 range() 함수는 별도의 start 와 stop 인자를 기대합니다. 그것들이 따로 있지 않으면, 리스트와 튜플로부터 인자를 언 패킹하기 위해 *-연산자를 사용해서 함수를 호출하면 됩니다:


    引数がすでにリストやタプルになっていて、個別な位置引数を要求する関数呼び出しに渡すためにアンパックする必要がある場合には、逆の状況が起こります。例えば、組み込み関数 range() は引数 start と stop を別に与える必要があります。個別に引数を与えることができない場合、関数呼び出しを * 演算子を使って書き、リストやタプルから引数をアンパックします:


    >>>
    >>> list(range(3, 6))            # normal call with separate arguments
    [3, 4, 5]
    >>> args = [3, 6]
    >>> list(range(*args))            # call with arguments unpacked from a list
    [3, 4, 5]
    

    같은 방식으로 딕셔너리도 **-연산자를 써서 키워드 인자를 전달할 수 있습니다:

    同じやりかたで、** オペレータを使って辞書でもキーワード引数を渡すことができます:

    >>>
    >>> def parrot(voltage, state='a stiff', action='voom'):
    ...     print("-- This parrot wouldn't", action, end=' ')
    ...     print("if you put", voltage, "volts through it.", end=' ')
    ...     print("E's", state, "!")
    ...
    >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
    >>> parrot(**d)
    -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
    

    4.7.5. 람다 표현식

    4.7.5. ラムダ式


    lambda 키워드들 사용해서 작고 이름 없는 함수를 만들 수 있습니다. 이 함수는 두 인자의 합을 돌려줍니다: lambda a, b: a+b. 함수 객체가 있어야 하는 곳이면 어디나 람다 함수가 사용될 수 있습니다. 문법적으로는 하나의 표현식으로 제한됩니다. 의미적으로는, 일반적인 함수 정의의 편의 문법일 뿐입니다. 중첩된 함수 정의처럼, 람다 함수는 둘러싸는 스코프에 있는 변수들을 참조할 수 있습니다:


    キーワード lambda を使うと、名前のない小さな関数を生成できます。例えば lambdaa, b: a+b は、二つの引数の和を返す関数です。ラムダ式の関数は、関数オブジェクトが要求されている場所にならどこでも使うことができます。ラムダ式は、構文上単一の式に制限されています。意味付け的には、ラムダ形式は単に通常の関数定義に構文的な糖衣をかぶせたものに過ぎません。入れ子構造になった関数定義と同様、ラムダ式もそれを取り囲むスコープから変数を参照することができます:


    >>>
    >>> def make_incrementor(n):
    ...     return lambda x: x + n
    ...
    >>> f = make_incrementor(42)
    >>> f(0)
    42
    >>> f(1)
    43
    

    위의 예는 함수를 돌려주기 위해 람다 표현식을 사용합니다. 또 다른 용도는 작은 함수를 인자로 전달하는 것입니다:

    上記の例は、関数を返すところでラムダ式を使っています。

    もう1つの例では、ちょっとした関数を引数として渡すのに使っています:

    >>>
    >>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
    >>> pairs.sort(key=lambda pair: pair[1])
    >>> pairs
    [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
    

    4.7.6. 도큐멘테이션 문자열

    4.7.6. ドキュメンテーション文字列


    여기에 도큐멘테이션 문자열의 내용과 포매팅에 관한 몇 가지 관례가 있습니다.

    ドキュメンテーション文字列については、その内容と書式に関する慣習をいくつか挙げます。



    첫 줄은 항상 객체의 목적을 짧고, 간결하게 요약해야 합니다. 간결함을 위해, 객체의 이름이나 형을 명시적으로 언급하지 않아야 하는데, 이것들은 다른 방법으로 제공되기 때문입니다 (이름이 함수의 작업을 설명하는 동사라면 예외입니다). 이 줄은 대문자로 시작하고 마침표로 끝나야 합니다.


    最初の行は、常に対象物の目的を短く簡潔にまとめたものでなくてはなりません。簡潔に書くために、対象物の名前や型を明示する必要はありません。名前や型は他の方法でも得られるからです (名前がたまたま関数の演算内容を記述する動詞である場合は例外です)。最初の行は大文字で始まり、ピリオドで終わっていなければなりません。



    도큐멘테이션 문자열에 여러 줄이 있다면, 두 번째 줄은 비어있어서, 시각적으로 요약과 나머지 설명을 분리해야 합니다. 뒤따르는 줄들은 하나나 그 이상의 문단으로, 객체의 호출 규약, 부작용 등을 설명해야 합니다.


    ドキュメンテーション文字列中にさらに記述すべき行がある場合、二行目は空行にし、まとめの行と残りの記述部分を視覚的に分離します。つづく行は一つまたはそれ以上の段落で、対象物の呼び出し規約や副作用について記述します。



    파이썬 파서는 여러 줄 문자열 리터럴에서 들여쓰기를 제거하지 않기 때문에, 설명서를 처리하는 도구들은 필요하면 들여쓰기를 제거합니다. 


    Python のパーザは複数行にわたる Python 文字列リテラルからインデントを剥ぎ取らないので、ドキュメントを処理するツールでは必要に応じてインデントを剥ぎ取らなければなりません。


    이것은 다음과 같은 관례를 사용합니다. 문자열의 첫줄 뒤에 오는 첫 번째 비어있지 않은 줄이 전체 도튜멘테이션 문자열의 들여쓰기 수준을 결정합니다. 

    (우리는 첫 줄을 사용할 수 없는데, 일반적으로 문자열을 시작하는 따옴표에 붙어있어서 들여쓰기가 문자열 리터럴의 것을 반영하지 않기 때문입니다.) 


    この処理は以下の規約に従って行います。最初の行の 後にある 空行でない最初の行が、ドキュメント全体のインデントの量を決めます。

    (最初の行は通常、文字列を開始するクオートに隣り合っているので、インデントが文字列リテラル中に現れないためです。) 


    이 들여쓰기와 "동등한" 공백이 문자열의 모든 줄의 시작 부분에서 제거됩니다. 덜 들여쓰기 된 줄이 나타나지는 말아야 하지만, 나타난다면 모든 앞부분의 공백이 제거됩니다.


    このインデント量と "等価な" 空白が、文字列のすべての行頭から剥ぎ取られます。インデントの量が少ない行を書いてはならないのですが、もしそういう行があると、先頭の空白すべてが剥ぎ取られます。



     공백의 동등성은 탭 확장 (보통 8개의 스페이스) 후에 검사됩니다.

    インデントの空白の大きさが等しいかどうかは、タブ文字を (通常は 8 文字のスペースとして) 展開した後に調べられます。



    여기 여러 줄 독스트링의 예가 있습니다:

    以下に複数行のドキュメンテーション文字列の例を示します:

    >>>
    >>> def my_function():
    ...     """Do nothing, but document it.
    ...
    ...     No, really, it doesn't do anything.
    ...     """
    ...     pass
    ...
    >>> print(my_function.__doc__)
    Do nothing, but document it.
    
        No, really, it doesn't do anything.
    

    4.7.7. 함수 어노테이션

    4.7.7. 関数のアノテーション


    함수 어노테이션 은 사용자 정의 함수가 사용하는 형들에 대한 완전히 선택적인 메타데이터 정보입니다 (자세한 내용은 PEP 3107 과 PEP 484 를 보세요).

    関数アノテーション はユーザ定義関数で使用される型についての完全にオプションなメタデータ情報です (詳細は PEP 3107 と PEP 484 を参照してください)。


    어노테이션은 함수의 __annotations__ 어트리뷰트에 딕셔너리로 저장되고 함수의 다른 부분에는 아무런 영향을 미치지 않습니다. 

    アノテーション は関数の __annotations__ 属性に辞書として格納され、関数の他の部分には何も影響がありません。


    매개변수 어노테이션은 매개변수 이름 뒤에 오는 콜론으로 정의되는데, 값을 구할 때 어노테이션의 값을 주는 표현식이 뒤따릅니다. 반환 값 어노테이션은 리터럴 -> 와 그 뒤를 따르는 표현식으로 정의되는데, 매개변수 목록과 def 문의 끝을 나타내는 콜론 사이에 놓입니다. 다음 예에서 위치 인자, 키워드 인자, 반환 값이 어노테이트 됩니다:


     パラメータアノテーションは、パラメータ名の後にコロンを続けることによって定義され、その後にアノテーションの値として評価される式が置かれます。 戻り値アノテーションは、パラメータリストと def ステートメントの終わりを表すコロンの間に置かれたリテラル -> によって定義され、その後に式が続きます。次の例は位置引数とキーワード引数、そして戻り値アノテーションを持っています:

    >>>
    >>> def f(ham: str, eggs: str = 'eggs') -> str:
    ...     print("Annotations:", f.__annotations__)
    ...     print("Arguments:", ham, eggs)
    ...     return ham + ' and ' + eggs
    ...
    >>> f('spam')
    Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
    Arguments: spam eggs
    'spam and eggs'
    

    4.8. 막간극: 코딩 스타일

    4.8. 間奏曲: コーディングスタイル


    이제 여러분은 파이썬의 더 길고, 더 복잡한 조각들을 작성하려고 합니다, 코딩 스타일 에 대해 말할 적절한 시간입니다. 대부분 언어는 서로 다른 스타일로 작성될 (또는 더 간략하게, 포맷될) 수 있습니다; 어떤 것들은 다른 것들보다 더 읽기 쉽습니다. 다른 사람들이 여러분의 코드를 읽기 쉽게 만드는 것은 항상 좋은 생각이고, 훌륭한 코딩 스타일을 도입하는 것은 그렇게 하는 데 큰 도움을 줍니다.


    これからより長くより複雑な Python のコードを書いていくので、そろそろ コーディングスタイル について語っても良い頃です。ほとんどの言語は様々なスタイルで書け (もっと簡潔に言えば フォーマットでき)、スタイルによって読み易さが異なります。他人にとって読み易いコードにしようとするのはどんなときでも良い考えであり、良いコーディングスタイルを採用することが非常に強力な助けになります。



    파이썬을 위해, 대부분 프로젝트가 고수하는 스타일 가이드로 PEP 8 이 나왔습니다; 이것은 매우 읽기 쉽고 눈이 편안한 코딩 스타일을 장려합니다. 모든 파이썬 개발자는 언젠가는 이 문서를 읽어야 합니다; 여러분을 위해 가장 중요한 부분들을 추려봤습니다:


    Python には、ほとんどのプロジェクトが守っているスタイルガイドとして PEP 8 があります。それは非常に読み易く目に優しいコーディングスタイルを推奨しています。全ての Python 開発者はある時点でそれを読むべきです。ここに最も重要な点を抜き出しておきます:

    • 들려 쓰기에 4-스페이스를 사용하고, 탭을 사용하지 마세요.

      4개의 스페이스는 작은 들여쓰기 (더 많은 중첩 도를 허락한다) 와 큰 들여쓰기 (읽기 쉽다) 사이의 좋은 절충입니다. 탭은 혼란을 일으키고, 없애는 것이 최선입니다.

    • 79자를 넘지 않도록 줄 넘김 하세요.

      이것은 작은 화면을 가진 사용자를 돕고 큰 화면에서는 여러 코드 파일들을 나란히 볼 수 있게 합니다.

    • 함수, 클래스, 함수 내의 큰 코드 블록 사이에 빈 줄을 넣어 분리하세요.

    • 가능하다면, 주석은 별도의 줄로 넣으세요.

    • 독스트링을 사용하세요.

    • 연산자들 주변과 콤마 뒤에 스페이스를 넣고, 괄호 바로 안쪽에는 스페이스를 넣지 마세요: a = f(1, 2) + g(3, 4).

    • 클래스와 함수들에 일관성 있는 이름을 붙이세요; 관례는 클래스의 경우 CamelCase, 함수와 메서드의 경우 lower_case_with_underscores 입니다. 첫 번째 메서드 인자의 이름으로는 항상 self 를 사용하세요 (클래스와 메서드에 대한 자세한 내용은 클래스와의 첫 만남 을 보세요).

    • 여러분의 코드를 국제적인 환경에서 사용하려고 한다면 특별한 인코딩을 사용하지 마세요. 어떤 경우에도 파이썬의 기본, UTF-8, 또는 단순 ASCII조차, 이 최선입니다.

    • 마찬가지로, 다른 언어를 사용하는 사람이 코드를 읽거나 유지할 약간의 가능성만 있더라도, 식별자에 ASCII 이외의 문자를 사용하지 마세요.

    • インデントには空白 4 つを使い、タブは使わないこと。

      空白 4 つは (深くネストできる) 小さいインデントと (読み易い) 大きいインデントのちょうど中間に当たります。タブは混乱させるので、使わずにおくのが良いです。

    • ソースコードの幅が 79 文字を越えないように行を折り返すこと。

      こうすることで小さいディスプレイを使っているユーザも読み易くなり、大きなディスプレイではソースコードファイルを並べることもできるようになります。

    • 関数やクラスや関数内の大きめのコードブロックの区切りに空行を使うこと。

    • 可能なら、コメントは行に独立で書くこと。

    • docstring を使うこと。

    • 演算子の前後とコンマの後には空白を入れ、括弧類のすぐ内側には空白を入れないこと: a = f(1, 2) + g(3, 4)

    • クラスや関数に一貫性のある名前を付けること。慣習では CamelCase をクラス名に使い、 lower_case_with_underscores を関数名やメソッド名に使います。常に self をメソッドの第 1 引数の名前 (クラスやメソッドについては クラス初見 を見よ) として使うこと。

    • あなたのコードを世界中で使ってもらうつもりなら、風変りなエンコーディングは使わないこと。どんな場合でも、Python のデフォルト UTF-8 またはプレーン ASCII が最も上手くいきます。

    • 同様に、ほんの少しでも他の言語を話す人がコードを読んだりメンテナンスする可能性があるのであれば、非 ASCII 文字も識別子に使うべきではありません。


    각주

    [1]실제로, 객체 참조에 의한 호출 (call by object reference)이 더 좋은 표현인데, 가변 객체가 전달되면, 호출자는 피호출자가 만든 변경을 볼 수 있기 때문입니다 (가령 리스트에 항목을 추가합니다).
    [1]実際には、オブジェクトへの参照渡し (call by object reference) と書けばよいのかもしれません。というのは、変更可能なオブジェクトが渡されると、関数の呼び出し側は、呼び出された側の関数がオブジェクトに行ったどんな変更 (例えばリストに挿入された要素) にも出くわすことになるからです。