4. Lebih Banyak Alat Pengatur Aliran *Control Flow*
***************************************************

Selain pernyataan "while" baru saja diperkenalkan, Python menggunakan
pernyataan kontrol aliran yang biasa dikenal dari bahasa lain, dengan
beberapa *twist*.


4.1. "if" Statements
====================

Mungkin tipe pernyataan yang paling terkenal adalah pernyataan "if".
Sebagai contoh:

   >>> x = int(raw_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

There can be zero or more "elif" parts, and the "else" part is
optional.  The keyword '"elif"' is short for 'else if', and is useful
to avoid excessive indentation.  An  "if" ... "elif" ... "elif" ...
sequence is a substitute for the "switch" or "case" statements found
in other languages.


4.2. "for" Statements
=====================

The "for" statement in Python differs a bit from what you may be used
to in C or Pascal.  Rather than always iterating over an arithmetic
progression of numbers (like in Pascal), or giving the user the
ability to define both the iteration step and halting condition (as
C), Python's "for" statement iterates over the items of any sequence
(a list or a string), in the order that they appear in the sequence.
For example (no pun intended):

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

If you need to modify the sequence you are iterating over while inside
the loop (for example to duplicate selected items), it is recommended
that you first make a copy.  Iterating over a sequence does not
implicitly make a copy.  The slice notation makes this especially
convenient:

   >>> 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']


4.3. Fungsi "range()"
=====================

If you do need to iterate over a sequence of numbers, the built-in
function "range()" comes in handy.  It generates lists containing
arithmetic progressions:

   >>> range(10)
   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

The given end point is never part of the generated list; "range(10)"
generates a list of 10 values, the legal indices for items of a
sequence of length 10.  It is possible to let the range start at
another number, or to specify a different increment (even negative;
sometimes this is called the 'step'):

   >>> range(5, 10)
   [5, 6, 7, 8, 9]
   >>> range(0, 10, 3)
   [0, 3, 6, 9]
   >>> range(-10, -100, -30)
   [-10, -40, -70]

Untuk beralih pada indeks urutan, Anda dapat menggabungkan "range()"
dan "len()" sebagai berikut:

   >>> 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

Dalam kebanyakan kasus seperti itu, bagaimanapun, lebih mudah untuk
menggunakan fungsi "enumerate()", lihat Teknik Perulangan.


4.4. "break" and "continue" Statements, and "else" Clauses on Loops
===================================================================

Pernyataan "break", seperti dalam C, keluar dari bagian terdalam yang
terlampir perulangan "for" atau "while".

Loop statements may have an "else" clause; it is executed when the
loop terminates through exhaustion of the list (with "for") or when
the condition becomes false (with "while"), but not when the loop is
terminated by a "break" statement.  This is exemplified by the
following loop, which searches for prime numbers:

   >>> 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

(Ya, ini adalah kode yang benar. Perhatikan baik-baik: klausul "else"
milik perulangan "for", **not** pernyataan "if".)

When used with a loop, the "else" clause has more in common with the
"else" clause of a "try" statement than it does that of "if"
statements: a "try" statement's "else" clause runs when no exception
occurs, and a loop's "else" clause runs when no "break" occurs. For
more on the "try" statement and exceptions, see Menangani
Pengecualian.

Pernyataan "continue", juga dipinjam dari C, melanjutkan dengan
pengulangan berikutnya dari loop:

   >>> 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" Statements
======================

Pernyataan "pass" tidak melakukan apa-apa. Ini dapat digunakan ketika
pernyataan diperlukan secara sintaksis tetapi program tidak memerlukan
tindakan. Sebagai contoh:

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

Ini biasanya digunakan untuk membuat kelas minimal:

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

Another place "pass" can be used is as a place-holder for a function
or conditional body when you are working on new code, allowing you to
keep thinking at a more abstract level.  The "pass" is silently
ignored:

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


4.6. Mendefinisikan Fungsi
==========================

Kita dapat membuat fungsi yang menulis seri Fibonacci ke batas acak
*arbitrary*:

   >>> 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,
   ...         a, b = b, a+b
   ...
   >>> # 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

Kata kunci "def" memperkenalkan fungsi *definition*. Itu harus diikuti
oleh nama fungsi dan daftar parameter formal yang di dalam tanda
kurung. Pernyataan yang membentuk tubuh fungsi mulai dari baris
berikutnya, dan harus diberi indentasi.

Pernyataan pertama dari tubuh fungsi secara opsional dapat berupa
string literal; string literal ini adalah string dokumentasi fungsi,
atau *docstring*. (Lebih lanjut tentang *docstring* dapat ditemukan di
bagian String Dokumentasi.) Ada alat yang menggunakan *docstring*
untuk secara otomatis menghasilkan dokumentasi online atau cetak, atau
untuk membiarkan pengguna menelusuri kode secara interaktif; itu
praktik yang baik untuk memasukkan dokumen dalam kode yang Anda tulis,
jadi biasakan seperti itu.

The *execution* of a function introduces a new symbol table used for
the local variables of the function.  More precisely, all variable
assignments in a function store the value in the local symbol table;
whereas variable references first look in the local symbol table, then
in the local symbol tables of enclosing functions, then in the global
symbol table, and finally in the table of built-in names. Thus, global
variables cannot be directly assigned a value within a function
(unless named in a "global" statement), although they may be
referenced.

Parameter aktual (*arguments*) untuk panggilan fungsi diperkenalkan
dalam tabel simbol lokal dari fungsi yang dipanggil ketika dipanggil;
dengan demikian, argumen dilewatkan menggunakan *call by value* (di
mana *value* selalu menjadi objek *reference*, bukan nilai objek). [1]
Ketika suatu fungsi memanggil fungsi lain, tabel simbol lokal baru
dibuat untuk panggilan itu.

Definisi fungsi memperkenalkan nama fungsi dalam tabel simbol saat
ini. Nilai nama fungsi memiliki tipe yang diakui oleh *interpreter*
sebagai fungsi yang ditentukan pengguna. Nilai ini dapat ditetapkan ke
nama lain yang kemudian dapat juga digunakan sebagai fungsi. Ini
berfungsi sebagai mekanisme penggantian nama umum:

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

Coming from other languages, you might object that "fib" is not a
function but a procedure since it doesn't return a value.  In fact,
even functions without a "return" statement do return a value, albeit
a rather boring one.  This value is called "None" (it's a built-in
name).  Writing the value "None" is normally suppressed by the
interpreter if it would be the only value written. You can see it if
you really want to using "print":

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

Sangat mudah untuk menulis fungsi yang mengembalikan daftar *list*
nomor seri Fibonacci, alih-alih mencetaknya:

   >>> 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]

Contoh ini, seperti biasa, menunjukkan beberapa fitur Python baru:

* The "return" statement returns with a value from a function.
  "return" without an expression argument returns "None". Falling off
  the end of a function also returns "None".

* Pernyataan "result.append(a)" memanggil *method* dari objek daftar
  *list* "result". Sebuah metode adalah fungsi yang 'milik' sebuah
  objek dan dinamai "obj.methodname", di mana "obj" adalah suatu objek
  (ini mungkin sebuah ekspresi), dan "methodname" adalah nama dari
  metode yang ditentukan oleh tipe objek. Jenis yang berbeda
  menentukan metode yang berbeda. Metode tipe yang berbeda mungkin
  memiliki nama yang sama tanpa menimbulkan ambiguitas. (Dimungkinkan
  untuk menentukan jenis dan metode objek Anda sendiri, menggunakan
  *classes*, lihat Kelas-kelas) Metode "append()" yang ditunjukkan
  pada contoh didefinisikan untuk objek daftar; itu menambahkan elemen
  baru di akhir daftar. Dalam contoh ini setara dengan "result =
  result + [a]", tetapi lebih efisien.


4.7. Lebih lanjut tentang Mendefinisikan Fungsi
===============================================

Dimungkinkan juga untuk mendefinisikan fungsi dengan sejumlah variabel
argumen. Ada tiga bentuk, yang bisa digabungkan.


4.7.1. Nilai Argumen Bawaan
---------------------------

Bentuk yang paling berguna adalah menentukan nilai bawaan untuk satu
atau lebih argumen. Ini menciptakan fungsi yang bisa dipanggil dengan
argumen yang lebih sedikit daripada yang didefinisikan untuk
diizinkan. Sebagai contoh:

   def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
       while True:
           ok = raw_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 IOError('refusenik user')
           print complaint

Fungsi ini dapat dipanggil dengan beberapa cara:

* hanya memberikan argumen wajib: "ask_ok('Do you really want to
  quit?')"

* memberikan salah satu argumen opsional: "ask_ok('OK to overwrite
  the file?', 2)"

* atau bahkan memberikan semua argumen: "ask_ok('OK to overwrite the
  file?', 2, 'Come on, only yes or no!')"

Contoh ini juga memperkenalkan kata kunci "in". Ini menguji apakah
suatu urutan berisi nilai tertentu atau tidak.

Nilai bawaan dievaluasi pada titik definisi fungsi dalam lingkup
*defining*, sehingga:

   i = 5

   def f(arg=i):
       print arg

   i = 6
   f()

akan mencetak "5".

**Peringatan penting:** Nilai bawaan dievaluasi hanya sekali. Ini
membuat perbedaan ketika bawaan adalah objek yang dapat diubah seperti
daftar *list*, kamus *dictionary*, atau *instances* dari sebagian
besar kelas. Misalnya, fungsi berikut mengakumulasi argumen yang
diteruskan pada panggilan berikutnya:

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

   print f(1)
   print f(2)
   print f(3)

Ini akan mencetak:

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

Jika Anda tidak ingin bawaan dibagi dengan panggilan berikutnya, Anda
dapat menulis fungsi seperti ini sebagai gantinya:

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


4.7.2. Argumen Kata Kunci *Keyword Arguments*
---------------------------------------------

Fungsi juga dapat dipanggil menggunakan *keyword argument* dari bentuk
"kwarg=value". Misalnya, fungsi berikut:

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

menerima satu argumen yang diperlukan ("voltage") dan tiga argumen
opsional ("state", "action", dan "type"). Fungsi ini dapat dipanggil
dengan salah satu cara berikut:

   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

tetapi semua pemanggilan berikut ini tidak valid:

   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

Dalam pemanggilan fungsi, argumen kata kunci *keyword argument* harus
mengikuti argumen posisi. Semua argumen kata kunci *keyword argument*
yang diteruskan harus cocok dengan salah satu argumen yang diterima
oleh fungsi (mis. "actor" bukan argumen yang valid untuk fungsi
"parrot"), dan urutannya tidak penting. Ini juga termasuk argumen non-
opsional (mis. "parrot(voltage=1000)" juga valid). Tidak ada argumen
yang dapat menerima nilai lebih dari sekali. Berikut ini contoh yang
gagal karena batasan ini:

   >>> 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'

When a final formal parameter of the form "**name" is present, it
receives a dictionary (see Mapping Types --- dict) containing all
keyword arguments except for those corresponding to a formal
parameter.  This may be combined with a formal parameter of the form
"*name" (described in the next subsection) which receives a tuple
containing the positional arguments beyond the formal parameter list.
("*name" must occur before "**name".) For example, if we define a
function like this:

   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
       keys = sorted(keywords.keys())
       for kw in keys:
           print kw, ":", keywords[kw]

Ini bisa disebut seperti ini:

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

dan tentu saja itu akan mencetak:

   -- 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.
   ----------------------------------------
   client : John Cleese
   shopkeeper : Michael Palin
   sketch : Cheese Shop Sketch

Note that the list of keyword argument names is created by sorting the
result of the keywords dictionary's "keys()" method before printing
its contents; if this is not done, the order in which the arguments
are printed is undefined.


4.7.3. Daftar Argumen Berubah-ubah *Arbitrary*
----------------------------------------------

Akhirnya, opsi yang paling jarang digunakan adalah menentukan bahwa
suatu fungsi dapat dipanggil dengan sejumlah argumen acak *arbitrary*.
Argumen-argumen ini akan dibungkus dalam sebuah tuple (lihat
*tuttuples*). Sebelum jumlah variabel argumen, nol atau lebih argumen
normal dapat muncul.

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


4.7.4. Pembukaan Paket *Unpacking* Daftar Argumen
-------------------------------------------------

Situasi sebaliknya terjadi ketika argumen sudah ada dalam daftar
*list* atau tuple tetapi perlu dibongkar untuk panggilan fungsi yang
membutuhkan argumen posisi terpisah. Sebagai contoh, fungsi bawaan
"range()" mengharapkan argumen terpisah *start* dan *stop*. Jika tidak
tersedia secara terpisah, tulis fungsi panggilan dengan operator-"*"
untuk membongkar argumen dari daftar *list* atau tuple:

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

Dengan cara yang sama, kamus dapat mengirimkan argumen kata kunci
dengan operator-"**":

   >>> def parrot(voltage, state='a stiff', action='voom'):
   ...     print "-- This parrot wouldn't", action,
   ...     print "if you put", voltage, "volts through it.",
   ...     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. Ekspresi Lambda
----------------------

Fungsi kecil anonim dapat dibuat dengan kata kunci "lambda". Fungsi
ini mengembalikan jumlah dari dua argumennya: "lambda a, b: a+b".
Fungsi Lambda dapat digunakan di mana pun objek fungsi diperlukan.
Mereka secara sintaksis terbatas pada satu ekspresi. Secara semantik,
mereka hanya pemanis sintaksis untuk definisi fungsi normal. Seperti
definisi fungsi bersarang, fungsi lambda dapat mereferensikan variabel
dari cakupan yang mengandung

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

Contoh di atas menggunakan ekspresi lambda untuk mengembalikan fungsi.
Penggunaan lain adalah untuk melewatkan fungsi kecil sebagai argumen:

   >>> 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. String Dokumentasi
-------------------------

There are emerging conventions about the content and formatting of
documentation strings.

Baris pertama harus selalu berupa ringkasan singkat dan ringkas dari
tujuan objek. Untuk singkatnya, itu tidak boleh secara eksplisit
menyatakan nama atau jenis objek, karena ini tersedia dengan cara lain
(kecuali jika nama tersebut merupakan kata kerja yang menggambarkan
operasi fungsi). Baris ini harus dimulai dengan huruf kapital dan
diakhiri dengan titik.

Jika ada lebih banyak baris dalam string dokumentasi, baris kedua
harus kosong, memisahkan ringkasan secara visual dari sisa deskripsi.
Baris berikut harus satu atau lebih paragraf yang menggambarkan
konvensi pemanggilan objek, efek sampingnya, dll.

Pengurai Python tidak menghapus lekukan dari string multi-baris
literal di Python, jadi alat yang memproses dokumentasi harus
menghapus indentasi jika diinginkan. Ini dilakukan dengan menggunakan
konvensi berikut. Baris tidak-kosong pertama *setelah* baris pertama
string menentukan jumlah indentasi untuk seluruh string dokumentasi.
(Kami tidak dapat menggunakan baris pertama karena umumnya berbatasan
dengan tanda kutip pembukaan string sehingga indentasinya tidak
terlihat dalam string literal.) Spasi "equivalent" untuk indentasi ini
kemudian dihilangkan dari awal semua baris string. Baris yang
indentasi lebih sedikit seharusnya tidak terjadi, tetapi jika terjadi
semua spasi *whitespace* utama harus dihilangkan. Kesetaraan spasi
harus diuji setelah ekspansi tab (hingga 8 spasi, biasanya).

Berikut adalah contoh dari multi-baris *docstring*:

   >>> 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.8. Intermezzo: Gaya *Coding*
==============================

Sekarang Anda akan menulis potongan Python yang lebih panjang dan
lebih kompleks, ini adalah saat yang tepat untuk berbicara tentang
*coding style*. Sebagian besar bahasa dapat ditulis (atau lebih
ringkas, *formatted*) dalam gaya yang berbeda; beberapa lebih mudah
dibaca daripada yang lain. Memudahkan orang lain untuk membaca kode
Anda selalu merupakan ide yang baik, dan mengadopsi gaya pengkodean
yang bagus sangat membantu untuk itu.

Untuk Python, **PEP 8** telah muncul sebagai panduan gaya yang
dipatuhi sebagian besar proyek; itu mempromosikan gaya pengkodean yang
sangat mudah dibaca dan menyenangkan. Setiap pengembang Python harus
membacanya di beberapa bagian; di sini adalah poin paling penting yang
ditunjukkan untuk Anda:

* Gunakan lekukan 4-spasi, dan tanpa tab.

  4 spasi adalah kompromi yang baik antara indentasi kecil
  (memungkinkan kedalaman bersarang lebih besar) dan indentasi besar
  (lebih mudah dibaca). Tab menimbulkan kebingungan, dan sebaiknya
  ditinggalkan.

* Bungkus *wrap* garis agar tidak melebihi 79 karakter.

  Ini membantu pengguna dengan tampilan kecil dan memungkinkan untuk
  memiliki beberapa file kode berdampingan pada tampilan yang lebih
  besar.

* Gunakan baris kosong untuk memisahkan fungsi dan kelas, dan blok
  kode yang lebih besar di dalam fungsi.

* Jika memungkinkan, berikan komentar pada baris terkait.

* Gunakan String Dokumentasi *docstrings*.

* Gunakan spasi di sekitar operator dan setelah koma, tetapi tidak
  secara langsung di dalam konstruksi kurung *bracketing*: "a = f(1,
  2) + g(3, 4)".

* Name your classes and functions consistently; the convention is to
  use "CamelCase" for classes and "lower_case_with_underscores" for
  functions and methods.  Always use "self" as the name for the first
  method argument (see Pandangan Pertama tentang Kelas for more on
  classes and methods).

* Don't use fancy encodings if your code is meant to be used in
  international environments.  Plain ASCII works best in any case.

-[ Catatan kaki ]-

[1] Sebenarnya, *call by object reference* akan menjadi deskripsi
    yang lebih baik, karena jika objek yang bisa ditransmisikan
    dilewatkan, pemanggil akan melihat perubahan yang dibuat oleh yang
    dipanggil *callee* (item dimasukkan ke dalam daftar).
