7. Masukan dan Keluaran
***********************

Ada beberapa cara untuk mempresentasikan keluaran suatu program; data
dapat dicetak dalam bentuk yang dapat dibaca manusia, atau ditulis ke
berkas untuk digunakan di masa mendatang. Bab ini akan membahas
beberapa kemungkinan.


7.1. Pemformatan Keluaran yang Lebih Menarik
============================================

So far we've encountered two ways of writing values: *expression
statements* and the "print" statement.  (A third way is using the
"write()" method of file objects; the standard output file can be
referenced as "sys.stdout". See the Library Reference for more
information on this.)

Often you'll want more control over the formatting of your output than
simply printing space-separated values.  There are two ways to format
your output; the first way is to do all the string handling yourself;
using string slicing and concatenation operations you can create any
layout you can imagine.  The string types have some methods that
perform useful operations for padding strings to a given column width;
these will be discussed shortly.  The second way is to use the
"str.format()" method.

The "string" module contains a "Template" class which offers yet
another way to substitute values into strings.

One question remains, of course: how do you convert values to strings?
Luckily, Python has ways to convert any value to a string: pass it to
the "repr()" or "str()" functions.

The "str()" function is meant to return representations of values
which are fairly human-readable, while "repr()" is meant to generate
representations which can be read by the interpreter (or will force a
"SyntaxError" if there is no equivalent syntax).  For objects which
don't have a particular representation for human consumption, "str()"
will return the same value as "repr()".  Many values, such as numbers
or structures like lists and dictionaries, have the same
representation using either function.  Strings and floating point
numbers, in particular, have two distinct representations.

Beberapa contoh:

   >>> s = 'Hello, world.'
   >>> str(s)
   'Hello, world.'
   >>> repr(s)
   "'Hello, world.'"
   >>> str(1.0/7.0)
   '0.142857142857'
   >>> repr(1.0/7.0)
   '0.14285714285714285'
   >>> x = 10 * 3.25
   >>> y = 200 * 200
   >>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
   >>> print s
   The value of x is 32.5, and y is 40000...
   >>> # The repr() of a string adds string quotes and backslashes:
   ... hello = 'hello, world\n'
   >>> hellos = repr(hello)
   >>> print hellos
   'hello, world\n'
   >>> # The argument to repr() may be any Python object:
   ... repr((x, y, ('spam', 'eggs')))
   "(32.5, 40000, ('spam', 'eggs'))"

Here are two ways to write a table of squares and cubes:

   >>> for x in range(1, 11):
   ...     print repr(x).rjust(2), repr(x*x).rjust(3),
   ...     # Note trailing comma on previous line
   ...     print repr(x*x*x).rjust(4)
   ...
    1   1    1
    2   4    8
    3   9   27
    4  16   64
    5  25  125
    6  36  216
    7  49  343
    8  64  512
    9  81  729
   10 100 1000

   >>> for x in range(1,11):
   ...     print '{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)
   ...
    1   1    1
    2   4    8
    3   9   27
    4  16   64
    5  25  125
    6  36  216
    7  49  343
    8  64  512
    9  81  729
   10 100 1000

(Note that in the first example, one space between each column was
added by the way "print" works: by default it adds spaces between its
arguments.)

This example demonstrates the "str.rjust()" method of string objects,
which right-justifies a string in a field of a given width by padding
it with spaces on the left.  There are similar methods "str.ljust()"
and "str.center()".  These methods do not write anything, they just
return a new string.  If the input string is too long, they don't
truncate it, but return it unchanged; this will mess up your column
lay-out but that's usually better than the alternative, which would be
lying about a value.  (If you really want truncation you can always
add a slice operation, as in "x.ljust(n)[:n]".)

Ada metode lain, "str.zfill()", yang melapisi string numerik di
sebelah kiri dengan nol. Itu mengerti tentang tanda plus dan minus:

   >>> '12'.zfill(5)
   '00012'
   >>> '-3.14'.zfill(7)
   '-003.14'
   >>> '3.14159265359'.zfill(5)
   '3.14159265359'

Penggunaan dasar metode "str.format()" terlihat seperti ini:

   >>> print 'We are the {} who say "{}!"'.format('knights', 'Ni')
   We are the knights who say "Ni!"

The brackets and characters within them (called format fields) are
replaced with the objects passed into the "str.format()" method.  A
number in the brackets refers to the position of the object passed
into the "str.format()" method.

   >>> print '{0} and {1}'.format('spam', 'eggs')
   spam and eggs
   >>> print '{1} and {0}'.format('spam', 'eggs')
   eggs and spam

Jika argumen kata kunci *keyword argument* digunakan dalam metode
"str.format()", nilainya dirujuk dengan menggunakan nama argumen.

   >>> print 'This {food} is {adjective}.'.format(
   ...       food='spam', adjective='absolutely horrible')
   This spam is absolutely horrible.

Argumen posisi dan kata kunci dapat dikombinasikan secara bergantian:

   >>> print 'The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',
   ...                                                    other='Georg')
   The story of Bill, Manfred, and Georg.

"'!s'" (apply "str()") and "'!r'" (apply "repr()") can be used to
convert the value before it is formatted.

   >>> import math
   >>> print 'The value of PI is approximately {}.'.format(math.pi)
   The value of PI is approximately 3.14159265359.
   >>> print 'The value of PI is approximately {!r}.'.format(math.pi)
   The value of PI is approximately 3.141592653589793.

An optional "':'" and format specifier can follow the field name. This
allows greater control over how the value is formatted.  The following
example rounds Pi to three places after the decimal.

>>> import math
>>> print 'The value of PI is approximately {0:.3f}.'.format(math.pi)
The value of PI is approximately 3.142.

Passing an integer after the "':'" will cause that field to be a
minimum number of characters wide.  This is useful for making tables
pretty.

   >>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
   >>> for name, phone in table.items():
   ...     print '{0:10} ==> {1:10d}'.format(name, phone)
   ...
   Jack       ==>       4098
   Dcab       ==>       7678
   Sjoerd     ==>       4127

Jika Anda memiliki string format yang sangat panjang yang tidak ingin
Anda pisahkan, alangkah baiknya jika Anda bisa mereferensikan variabel
yang akan diformat berdasarkan nama alih-alih berdasarkan posisi. Ini
dapat dilakukan hanya dengan melewatkan *dict* dan menggunakan tanda
kurung siku "'[]'" untuk mengakses kunci dari *dict*

   >>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
   >>> print ('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
   ...        'Dcab: {0[Dcab]:d}'.format(table))
   Jack: 4098; Sjoerd: 4127; Dcab: 8637678

Ini juga bisa dilakukan dengan memberikan tabel sebagai argumen kata
kunci *keyword argument* dengan notasi '**'.

   >>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
   >>> print 'Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)
   Jack: 4098; Sjoerd: 4127; Dcab: 8637678

Ini sangat berguna dalam kombinasi dengan fungsi bawaan "vars()", yang
mengembalikan *dictionary* yang berisi semua variabel lokal.

Untuk ikhtisar lengkap pemformatan string dengan "str.format()", lihat
Format String Syntax.


7.1.1. Pemformatan string lama
------------------------------

Operator "%" juga dapat digunakan untuk pemformatan string. Ini
menafsirkan argumen kiri seperti gaya "sprintf()"format string untuk
diterapkan pada argumen yang benar, dan mengembalikan string yang
dihasilkan dari operasi pemformatan ini. Sebagai contoh:

   >>> import math
   >>> print 'The value of PI is approximately %5.3f.' % math.pi
   The value of PI is approximately 3.142.

More information can be found in the String Formatting Operations
section.


7.2. Membaca dan Menulis Berkas
===============================

"open()" returns a file object, and is most commonly used with two
arguments: "open(filename, mode)".

   >>> f = open('workfile', 'w')
   >>> print f
   <open file 'workfile', mode 'w' at 80a0960>

Argumen pertama adalah string yang berisi nama file. Argumen kedua
adalah string lain yang berisi beberapa karakter yang menggambarkan
cara berkas akan digunakan. *mode* dapat "'r'" ketika file hanya akan
dibaca, "'w'" untuk hanya menulis (berkas yang ada dengan nama yang
sama akan dihapus), dan "'a'" membuka berkas untuk ditambahkan; setiap
data yang ditulis ke file secara otomatis ditambahkan ke bagian akhir.
"'r+'" membuka berkas untuk membaca dan menulis. Argumen *mode* adalah
opsional; "'r'" akan diasumsikan jika dihilangkan.

On Windows, "'b'" appended to the mode opens the file in binary mode,
so there are also modes like "'rb'", "'wb'", and "'r+b'".  Python on
Windows makes a distinction between text and binary files; the end-of-
line characters in text files are automatically altered slightly when
data is read or written.  This behind-the-scenes modification to file
data is fine for ASCII text files, but it'll corrupt binary data like
that in "JPEG" or "EXE" files.  Be very careful to use binary mode
when reading and writing such files.  On Unix, it doesn't hurt to
append a "'b'" to the mode, so you can use it platform-independently
for all binary files.


7.2.1. Metode Objek Berkas
--------------------------

Sisa contoh di bagian ini akan menganggap bahwa objek berkas bernama
"f" telah dibuat.

To read a file's contents, call "f.read(size)", which reads some
quantity of data and returns it as a string.  *size* is an optional
numeric argument.  When *size* is omitted or negative, the entire
contents of the file will be read and returned; it's your problem if
the file is twice as large as your machine's memory. Otherwise, at
most *size* bytes are read and returned.  If the end of the file has
been reached, "f.read()" will return an empty string ("""").

   >>> f.read()
   'This is the entire file.\n'
   >>> f.read()
   ''

"f.readline()" reads a single line from the file; a newline character
("\n") is left at the end of the string, and is only omitted on the
last line of the file if the file doesn't end in a newline.  This
makes the return value unambiguous; if "f.readline()" returns an empty
string, the end of the file has been reached, while a blank line is
represented by "'\n'", a string containing only a single newline.

   >>> f.readline()
   'This is the first line of the file.\n'
   >>> f.readline()
   'Second line of the file\n'
   >>> f.readline()
   ''

Untuk membaca baris dari file, Anda dapat mengulangi objek berkas. Ini
hemat memori, cepat, dan mengarah ke kode sederhana

   >>> for line in f:
           print line,

   This is the first line of the file.
   Second line of the file

Jika Anda ingin membaca semua baris file dalam daftar *list*, Anda
juga dapat menggunakan "list(f)" atau "f.readlines()".

"f.write(string)" writes the contents of *string* to the file,
returning "None".

   >>> f.write('This is a test\n')

To write something other than a string, it needs to be converted to a
string first:

   >>> value = ('the answer', 42)
   >>> s = str(value)
   >>> f.write(s)

"f.tell()" returns an integer giving the file object's current
position in the file, measured in bytes from the beginning of the
file.  To change the file object's position, use "f.seek(offset,
from_what)".  The position is computed from adding *offset* to a
reference point; the reference point is selected by the *from_what*
argument.  A *from_what* value of 0 measures from the beginning of the
file, 1 uses the current file position, and 2 uses the end of the file
as the reference point.  *from_what* can be omitted and defaults to 0,
using the beginning of the file as the reference point.

   >>> f = open('workfile', 'r+')
   >>> f.write('0123456789abcdef')
   >>> f.seek(5)      # Go to the 6th byte in the file
   >>> f.read(1)
   '5'
   >>> f.seek(-3, 2)  # Go to the 3rd byte before the end
   >>> f.read(1)
   'd'

When you're done with a file, call "f.close()" to close it and free up
any system resources taken up by the open file.  After calling
"f.close()", attempts to use the file object will automatically fail.

   >>> f.close()
   >>> f.read()
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ValueError: I/O operation on closed file

It is good practice to use the "with" keyword when dealing with file
objects.  This has the advantage that the file is properly closed
after its suite finishes, even if an exception is raised on the way.
It is also much shorter than writing equivalent "try"-"finally"
blocks:

   >>> with open('workfile', 'r') as f:
   ...     read_data = f.read()
   >>> f.closed
   True

Objek file memiliki beberapa metode tambahan, seperti "isatty()" dan
"truncate()" yang lebih jarang digunakan; bacalah Referensi Pustaka
untuk panduan lengkap untuk objek berkas.


7.2.2. Menyimpan data terstruktur dengan "json"
-----------------------------------------------

String dapat dengan mudah ditulis dan dibaca dari file. Angka
membutuhkan sedikit usaha, karena metode "read()" hanya mengembalikan
string, yang harus diteruskan ke fungsi seperti "int()", yang
mengambil string seperti "'123'" dan mengembalikan nilai numerik 123.
Ketika Anda ingin menyimpan tipe data yang lebih kompleks seperti
daftar *list* dan *dictionary* bersarang, penguraian dan pembuatan
serialisasi dengan tangan menjadi rumit.

Alih-alih membuat pengguna terus-menerus menulis dan men-debug kode
untuk menyimpan tipe data yang rumit ke berkas, Python memungkinkan
Anda untuk menggunakan format pertukaran data populer yang disebut
JSON (JavaScript Object Notation). Modul standar bernama "json" dapat
mengambil hierarki data Python, dan mengubahnya menjadi representasi
string; proses ini disebut *serializing*. Merekonstruksi data dari
representasi string disebut *deserializing*. Antara *serializing* dan
*deserializing*, string yang mewakili objek mungkin telah disimpan
dalam berkas atau data, atau dikirim melalui koneksi jaringan ke
beberapa mesin yang jauh.

Catatan: Format JSON umumnya digunakan oleh aplikasi modern untuk
  memungkinkan pertukaran data. Banyak programmer sudah terbiasa
  dengannya, yang membuatnya menjadi pilihan yang baik untuk
  interoperabilitas.

Jika Anda memiliki objek "x", Anda dapat melihat representasi string
JSON dengan baris kode sederhana:

   >>> import json
   >>> json.dumps([1, 'simple', 'list'])
   '[1, "simple", "list"]'

Another variant of the "dumps()" function, called "dump()", simply
serializes the object to a file.  So if "f" is a *file object* opened
for writing, we can do this:

   json.dump(x, f)

To decode the object again, if "f" is a *file object* which has been
opened for reading:

   x = json.load(f)

Teknik serialisasi sederhana ini dapat menangani daftar *list* dan
*dictionary*, tetapi membuat serialisasi *instance* kelas yang
berubah-ubah *arbitrary* di JSON membutuhkan sedikit usaha ekstra.
Referensi untuk modul "json" berisi penjelasan tentang ini.

lihat juga: "Pickle" - modul *pickle*

  Berlawanan dengan JSON, *pickle* adalah protokol yang memungkinkan
  serialisasi objek Python yang semena-mena *arbitrarily* kompleks.
  Dengan demikian, ini khusus untuk Python dan tidak dapat digunakan
  untuk berkomunikasi dengan aplikasi yang ditulis dalam bahasa lain.
  Ini juga tidak aman secara bawaan: *deserializing* *pickle* data
  yang berasal dari sumber yang tidak dipercaya dapat mengeksekusi
  kode semena-mena *arbitrary*, jika data dibuat oleh penyerang yang
  terampil.
