3. รู้จักไพธอน (An Informal Introduction to Python)

3.1 ใช้งานเป็นเครื่องคิดเลข (Using Python as a Calculator)
3.2 ลองเขียนสักสคริปต์นึง (First Steps Towards Programming)


ตัวอย่างจะใช้เครื่องหมาย # แทนคอมเมนต์
เช่น

# this is the first comment
SPAM = 1                 # and this is the second comment
                         # ... and now a third!
STRING = "# This is not a comment."


3.1 ใช้งานเป็นเครื่องคิดเลข (Using Python as a Calculator)

3.1.1 ตัวเลข (Numbers)

ในหมวดโต้ตอบ เราใช้แทนเครื่องคิดเลขได้เลย เช่น

>>> 2+2
4

>>> # This is a comment
... 2+2
4

>>> 2+2  # and a comment on the same line as code
4

>>> (50-5*6)/4
5

>>> # Integer division returns the floor:
... 7/3
2

>>> 7/-3
-3

กำหนดค่าให้ตัวแปรด้วย = ตามปกติ

>>> width = 20
>>> height = 5*9
>>> width * height
900

กำหนดทีละหลายตัวแปรพร้อมกันก็ได้

>>> x = y = z = 0  # Zero x, y and z
>>> x
0

>>> y
0

>>> z
0

รองรับทศนิยมลอยด้วย โดยมีหลักว่า ถ้าต้นทางเป็นจำนวนเต็ม ผลจะเป็นจำนวนเต็มด้วย ถ้าต้นทางเป็นทศนิยมลอย ผลจะเป็นทศนิยมลอยด้วย (ถ้าผสมกันก็จะเป็นทศนิยมลอยเช่นกัน)

>>> 3 * 3.75 / 1.5
7.5

>>> 7 / 2
3

>>> 7.0 / 2
3.5

จำนวนเชิงซ้อนก็ได้ โดยตัวเลขจินตภาพจะต้องต่อท้ายด้วย "j" หรือ "J" โดยมีรูปแบบเป็น "(real+imagj)" หรือเขียนแบบฟังก์ชั่นว่า "complex(real, imag)"

>>> 1j * 1J
(-1+0j)

>>> 1j * complex(0,1)
(-1+0j)

>>> 3+1j*3
(3+3j)

>>> (3+1j)*3
(9+3j)

>>> (1+2j)/(1+1j)
(1.5+0.5j)

ตัวเลขในจำนวนเชิงซ้อน จะถูกตีความเป็นทศนิยมลอยเสมอ และสามารถแยกตัวเลขจริงกับตัวเลขจินตภาพด้วยการเขียนในรูปแบบออปเจคต์คือ z.real และ z.imag

>>> a=1+0.5j
>>> a.real
1.0

>>> a.imag
0.5

ไม่สามารถใช้ฟังก์ชั่นการแปลงตัวเลขปกติ คือ float(), int() และ long() กับจำนวนเชิงซ้อนได้
แต่สามารถใช้ฟังก์ชั่น abs(z) หาค่าสัมบูรณ์ และใช้ z.real หาค่าจำนวนจริงของ z ได้

>>> a=3.0+4.0j

>>> float(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: can't convert complex to float; use abs(z)

>>> a.real
3.0

>>> a.imag
4.0

>>> abs(a)  # sqrt(a.real**2 + a.imag**2)
5.0

พิเศษสำหรับหมวดโต้ตอบ ค่าที่ถูกพิมพ์ออกมาเป็นครั้งสุดท้าย จะถูกเก็บไว้ในตัวแปรพิเศษคือ _ เราอาจนำตัวแปรนี้ไปใช้ในการคำนวนค่าต่อ ๆ ไป

>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625

>>> price + _
113.0625

>>> round(_, 2)
113.06

*** เนื่องจาก _ เป็นตัวแปรพิเศษดังกล่าว ดังนั้นเพื่อป้องกันความผิดพลาด จึงไม่ควรกำหนดค่าให้มัน ควรใช้เป็นตัวแปรเฉพาะตามวัตถุประสงค์ของไพธอนเท่านั้น

3.1.2 สตริงก์ (Strings)

สามารถใช้งานสตริงก์ได้ทั้งอัญประกาศเดี่ยวและคู่ (Single & Double quote)

>>> 'spam eggs'
'spam eggs'

>>> 'doesn\'t'
"doesn't"

>>> "doesn't"
"doesn't"

>>> '"Yes," he said.'
'"Yes," he said.'

>>> "\"Yes,\" he said."
'"Yes," he said.'

>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'

ใช้สตริงก์แบบหลายบรรทัด โดย...

  • ใช้อักขระ \ (Backslash) ในการแยก เช่น
    >>> hello = "This is a rather long string containing\n\
    ... several lines of text just as you would do in C.\n\
    ...     Note that whitespace at the beginning of the line is\
    ...  significant."
    
    >>> print hello
    This is a rather long string containing
    several lines of text just as you would do in C.
        Note that whitespace at the beginning of the line is significant.
  • ใช้สตริงก์ดิบ (raw string) โดยใช้ r นำหน้าเครื่องหมายอัญประกาศ ซึ่งก็จะให้ผลแบบดิบ ๆ
    >>> hello = r"This is a rather long string containing\n\
    ... several lines of text much as you would do in C."
    
    >>> print hello
    This is a rather long string containing\n\
    several lines of text much as you would do in C.
  • หรือใช้ตรีอัญประกาศ คือ """ หรือ ''' อันนี้ใช้ง่ายแบบธรรมชาติ
    >>> print """
    ... Usage: thingy [OPTIONS] 
    ...      -h                        Display this usage message
    ...      -H hostname               Hostname to connect to
    ... """
    Usage: thingy [OPTIONS] 
         -h                        Display this usage message
         -H hostname               Hostname to connect to
  • ที่สำคัญคือ เริ่มต้นด้วยอัญประกาศแบบไหน ก็ต้องปิดท้ายด้วยอัญประกาศแบบนั้นเสมอ

ใช้ + ในการเชื่อมสตริงก์ และ * ในการเชื่อมแบบซ้ำ ๆ

>>> word = 'Help' + 'A'
>>> word
'HelpA'

>>> '<' + word*5 + '>'
'<HelpAHelpAHelpAHelpAHelpA>'

ในหมวดโต้ตอบนี้ ช่องว่างระหว่างสตริงก์ถูกประมวลผลเป็นการเชื่อมสคริงก์ แต่ใช้ได้กับสคริงก์อย่างเดียว ฟังกืชั่นไม่เกี่ยว

>>> 'str' 'ing'                   #  <-  This is ok
'string'

>>> 'str'.strip() + 'ing'   #  <-  This is ok
'string'

>>> 'str'.strip() 'ing'     #  <-  This is invalid
  File "<stdin>", line 1, in ?
    'str'.strip() 'ing'
                      ^
SyntaxError: invalid syntax

สตริงก์ทำตัวเป็น อาเรย์ของอักขระ ดังนั้นจึงสามารถอ้างถึงแบบอาเรย์ได้ โดยอ้างเป็นช่วงด้วย : (colon) ซึ่งไพธอนเรียกช่วงของสตริงก์นี้ว่าสไลซ์ (slice)

>>> word[4]
'A'

>>> word[0:2]
'He'

>>> word[2:4]
'lp'

ถ้าละเลย ไม่ใส่ค่าดัชนี ถ้าเป็นดัชนีข้างหน้า จะถูกตีความเป็นศูนย์ และตัวหลังจะถูกตีความเป็นความยาวสตริงก์

>>> word[:2]    # The first two characters
'He'

>>> word[2:]    # Everything except the first two characters
'lpA'

สตริงก์ในไพธอนไม่เหมือนกับภาษาซี ไพธอนไม่สามารถเปลี่ยนค่าสคริงก์โดยอ้างจากดัชนีได้

>>> word[0] = 'x'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: object doesn't support item assignment

>>> word[:1] = 'Splat'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: object doesn't support slice assignment

แต่ก็สร้างใหม่ได้ไม่ยาก

>>> 'x' + word[1:]
'xelpA'

>>> 'Splat' + word[4]
'SplatA'

>>> x = word[:]
>>> x = 'Splat' + x[4]
>>> x
'SplatA'

ลูกเล่นเล็กน้อย ให้ผลเป็น s เหมือนเดิม

>>> word[:2] + word[2:]
'HelpA'

>>> word[:3] + word[3:]
'HelpA'

ดัชนีที่มีค่านอกช่วงที่มีจริง ไพธอนจะแสดงเป็นอักขระว่างให้ โดยไม่รายงานความผิดพลาด

>>> word[1:100]
'elpA'

>>> word[10:]
''

>>> word[2:1]
''

ดัชนีเป็นค่าลบ จะเป็นการนับจากขวามาซ้าย

>>> word[-1]     # The last character
'A'

>>> word[-2]     # The last-but-one character
'p'

>>> word[-2:]    # The last two characters
'pA'

>>> word[:-2]    # Everything except the last two characters
'Hel'

ยกเว้น -0 มีค่าเท่ากับ 0 จึงนับจากซ้ายเป็นปกติ

>>> word[-0]     # (since -0 equals 0)
'H'

ถ้าระบุดัชนีเป็นช่วง ไพธอนจะจัดการค่าที่ไม่เป็นจริงให้ทั้งหมด แต่ถ้าใช้ดัชนีตัวเดียว ถ้าค่าดัชนีไม่เป็นจริง ไพธอนจะแสดงค่าผิดพลาด

>>> word[-100:]
'HelpA'

>>> word[-10]    # error
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IndexError: string index out of range

เทคนิกการจำเรื่องช่วงดัชนีคือ ให้คิดว่าดัชนีเป็นค่าที่อยู่ระหว่างอักขระ ที่ซ้ายสุดเป็น 0 และขวาสุดเป็นขนาดสตริงก์

 +---+---+---+---+---+ 
 | H | e | l | p | A |
 +---+---+---+---+---+ 
 0   1   2   3   4   5 
-5  -4  -3  -2  -1

สำหรับดัชนีที่เป็นค่าบวก ขนาดของสไลซ์คือผลต่างของค่าตัวเลขดัชนี เช่นขนาดของ word[1:3] คือ 2

เราหาขนาดของสตริงก์ด้วยฟังก์ชั่น len()

>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34

ดูเพิ่มเติม
เรื่อง

3.1.3 สตริงแบบยูนิโค๊ด (Unicode Strings)

เริ่มใช้ในไพธอนรุ่น 2.0 ในการจัดการข้อมูลแบบยูนิโค๊ด (ดู http://www.unicode.org/)

ใช้งานเหมือนสตริงก์ปกติ เวลาเขียนใช้ u นำหน้าอัญประกาศ

>>> u'Hello World !'
u'Hello World !'

ถ้าอักขระยูนิโค๊ดตัวไหนพิมพ์ยาก อาจใช้ \u (Python Unicode-Escape) นำหน้า
แสดงตัวอย่างเป็นอักขระเคาะวรรค (space) คือ \u0020

>>> u'Hello\u0020World !'
u'Hello World !'

ในการใช้สตริงก์ดิบกับยูนิโค๊ด ใช้ ur นำหน้า และต้องใส่อักขระ \ สองตัว ไม่งั้นจะตีความเป็น Python Unicode-Escape ดูยุ่งยากเล็กน้อย แต่จะมีประโยชน์สำหรับการใช้งาน regular expresstion

>>> ur'Hello\u0020World !'
u'Hello World !'

>>> ur'Hello\\u0020World !'
u'Hello\\\\u0020World !'

จริง ๆ แล้ว ไพธอนเก็บข้อมูลสตริงก์เป็นอักขระยูนิโค๊ดอยู่แล้ว (อาจเปลี่ยนแปลงในรุ่นหน้า คือรุ่น 3.0) ดังนั้นการใช้ฟังก์ชั่น str() กับอักขระยูนิโค๊ด จึงแสดงข้อผิดพลาด เว้นเสียแต่ว่าอักขระเหล่านั้นมีรหัส ASCII น้อยกว่า 127 คือเป็นภาษาอังกฤษธรรมดา

>>> u"abc"
u'abc'

>>> str(u"abc")
'abc'

>>> u"äöü"
u'\xe4\xf6\xfc'

>>> str(u"äöü")
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

การแปลงการเข้ารหัสอักขระเป็นรหัสอักขระต่าง ๆ เราใช้ฟังก์ชั่น encode()

>>> u"äöü".encode('utf-8')
'\xc3\xa4\xc3\xb6\xc3\xbc'

เป็นการแปลงสตริงก์ u"äöü" ไปเป้นสตริงก์แบบ utf-8

และใช้ฟังก์ชั่น unicode() ในการแปลงกลับ

>>> unicode('\xc3\xa4\xc3\xb6\xc3\xbc', 'utf-8')
u'\xe4\xf6\xfc'
3.1.4 ลิสต์ (Lists)

ข้อมูลลิสต์ถือเป็นข้อเด่นที่สุดข้อหนึ่งของไพธอน เป็นการเอาข้อมูลมาจัดให้อยู่ในกลุ่มเดียวกัน ภายใต้เครื่องหมายวงเล็บ [] โดยข้อมูลย่อยไม่จำเป็นต้องเป็นชนิดเดียวกัน

>>> a = ['spam', 'eggs', 100, 1234]
>>> a
['spam', 'eggs', 100, 1234]

การใช้ดัชนีในการอ้างถึงข้อมูลย่อยภายใน ใช้งานคล้ายกับสตริงก์

>>> a[0]
'spam'

>>> a[3]
1234

>>> a[-2]
100

>>> a[1:-1]
['eggs', 100]

>>> a[:2] + ['bacon', 2*2]
['spam', 'eggs', 'bacon', 4]

>>> 3*a[:3] + ['Boo!']
['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boo!']

แต่ต่างจากสตริงก์ตรงที่ข้อมูลย่อยภายในสามารถเปลี่ยนแปลงค่าได้ โดยการอ้างจากดัชนี

>>> a
['spam', 'eggs', 100, 1234]

>>> a[2] = a[2] + 23
>>> a
['spam', 'eggs', 123, 1234]

>>> a[2] = 10
>>> a
['spam', 'eggs', 10, 1234]

กำหนดค่าเป็นช่วงสไลซ์ก็ได้

>>> # Replace some items:
... a[0:2] = [1, 12]
>>> a
[1, 12, 123, 1234]

>>> # Remove some:
... a[0:2] = []
>>> a
[123, 1234]

>>> # Insert some:
... a[1:1] = ['bletch', 'xyzzy']
>>> a
[123, 'bletch', 'xyzzy', 1234]

>>> # Insert (a copy of) itself at the beginning
... a[:0] = a
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]

>>> # Clear the list: replace all items with an empty list
... a[:] = []
>>> a
[]

ใช้ฟังก์ชั่น len() ในการหาขนาดลิสต์ (จำนวนสมาชิก)

>>> len(a)
8

ซ้อนลิสต์ในลิสต์ก็ได้

>>> q = [2, 3]
>>> p = [1, q, 4]
>>> len(p)
3

>>> p[1]
[2, 3]

>>> p[1][0]
2

>>> p[1].append('xtra')     # See section 5.1
>>> p
[1, [2, 3, 'xtra'], 4]

>>> q
[2, 3, 'xtra']

จากตัวอย่างนี้ ตัวแปร p[1] กับตัวแปร q เป็นออปเจกต์อันเดียวกัน (การใช้ลิสต์ต้องระวังตรงนี้นิดนึง)


3.2 ลองเขียนสักสคริปต์นึง (First Steps Towards Programming)

การใช้งานไพธอนง่ายตรงนี้ คือเราจะเขียนโค๊ดเล็ก ๆ แล้วก็จับมาต่อ ๆ กันไป กลายเป็นสคริปต์ที่ซับซ้อนสำหรับใช้งานจริง
เริ่มด้วยโค๊ดอมตะ อนุกรมฟิโบแนคซี่ (Fibonacci)

>>> # Fibonacci series:
... # the sum of two elements defines the next
... a, b = 0, 1

>>> while b < 10:
...       print b
...       a, b = b, a+b
... 
1
1
2
3
5
8

ความรู้ใหม่

  • บรรทัดแรกเป็นการกำหนดหลายตัวแปรทีละหลายค่า (multiple assignment) ในที่นี้ a คือ 0 และ b คือ 1
  • การวนรอบโดยใช้คำสั่ง while คำสั่งนี้จะตีความว่า นิพจน์หลังคำสั่ง while จะเป็นอะไรก็ได้ที่ไม่ใช่ศุนย์หรือค่าว่าง จะเป็นจริงเสมอ โดยที่การเปรียบเทียบจะใช้สัญญลักษณ์เหมือนภาษาซี คือ < คือน้อยกว่า > คือมากกว่า == คือเท่ากันกับ <= คือน้อยกว่าหรือเท่ากับ >= คือมากกว่าหรือเท่ากับ และ != คือไม่เท่ากับ
  • สักเกตุการเยื้องของบล๊อก ซึ่งไพธอนใช้การเยื้องในการจัดกลุ่มบล๊อก (สำหรับกลุ่มเดียวกัน ต้องเยื้องให้เท่ากัน)
  • คำสั่ง print มีข้อพิเศษคือ
    • ไม่เกี่ยงชนิดข้อมูล ทำให้เขียนโค๊ดง่าย
      >>> i = 256*256
      >>> print 'The value of i is', i
      The value of i is 65536
    • ใช้ , หากไม่ต้องการขึ้นบรรทัดใหม่
      >>> a, b = 0, 1
      >>> while b < 1000:
      ...     print b,
      ...     a, b = b, a+b
      ... 
      1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987