ความเเตกต่าง ระหว่าง python 2 - python 3

แชร์ความรู้ภาษา Python ไพทอน การเขียนโปรแกรมภาษาไพทอน

Moderator: mindphp, ผู้ดูแลกระดาน

ภาพประจำตัวสมาชิก
Jom07
PHP Super Hero Member
PHP Super Hero Member
โพสต์: 506
ลงทะเบียนเมื่อ: 08/01/2018 9:56 am

ความเเตกต่าง ระหว่าง python 2 - python 3

โพสต์โดย Jom07 » 16/02/2018 1:48 pm

Python 3 มีความแตกต่างไปจาก Python 2 โค้ดที่เขียนด้วย Python 2 สามารถนำมาใช้ใน Python 3 แต่ต้องมีการปรับแก้โค้ตเป็นบางส่วน สิ่งที่แตกต่าง คือ

1.การตั้งชื่อตัวแปร
ใน Python 2 ชื่อตัวแปรจะใช้ได้แค่อักษรโรมัน 26 ตัวหลัก (ทั้งพิมพ์ใหญ่และพิมพ์เล็ก) และตัวเลข 0 ถึง 9 แล้วก็สัญลักษณ์ขีดล่าง _ แต่ใน Python 3 สามารถตั้งชื่อเป็นอักษรชนิดอื่นได้ เช่น
- อักษรโรมันที่มีสัญลักษณ์เพิ่มเติม (áéíóúýäëïöüÿøåæñ ฯลฯ)
- อักษรกรีก (αβγδεζηθικλμνξοπρστυφχψω ฯลฯ)
- อักษรไทย ลาว เขมร เวียดนาม จีน ญี่ปุ่น เกาหลี ฯลฯ (ไทย ລາວ ខ្មែរ Việt 漢字 カタカナ ひらがな 한글 ฯลฯ)
ตัวอย่าง

โค้ด: เลือกทั้งหมด

นักศึกษามหาวิทยาลัยที่หนึ่งมีจำนวนนิสิต = 22,200

ใน Python 3 จะไม่มีอะไรเกิดขึ้น แต่ใน Python 2 จะขึ้นว่า

โค้ด: เลือกทั้งหมด

SyntaxError: invalid syntax

เพราะว่า Syntax ไม่สามารถใช้ได้

2.ชนิดข้อมูลจำนวนเต็ม
ใน Python 2 นั้นจำนวนเต็มถูกแบ่งเป็น 2 ชนิดคือ int กับ long แต่ใน Python 3 ได้รวมกันเป็นชนิดเดียวคือ int โดยค่า int จะมีขอบเขตจำกัดอยู่ค่าหนึ่ง ค่าสูงสุดของ int นั้นมีจำกัดอยู่แล้วแต่เครื่อง
ตัวอย่าง

โค้ด: เลือกทั้งหมด

import sys
print(sys.maxint)

จะได้ค่าสูงสุดของ int ออกมาใน Python 3 จะได้ผลลัพธ์เป็น

โค้ด: เลือกทั้งหมด

1208925819614629174706176

แต่ใน Python 2 จะได้ผลลัพธ์เป็น

โค้ด: เลือกทั้งหมด

1208925819614629174706176L

สิ่งที่ต่างกันคือใน Python 2 มีตัว L เพิ่มขึ้นมา ซึ่งตัว L ในที่นี้เป็นตัวบ่งบอกว่าเป็นข้อมูลชนิด long หมายความว่าใน Python 2 ถ้าหากใส่เลขที่ใหญ่เกินขอบเขตที่จะเป็น int ได้ก็จะถูกเก็บในรูปของ long ใน Python 3 จะใหญ่แค่ไหนก็ยังเป็น int และจะไม่มีข้อมูลชนิด long
ดังนั้นหากพิมพ์ 1208925819614629174706176L ลงใน Python 3 ก็จะขึ้นว่า

โค้ด: เลือกทั้งหมด

SyntaxError: invalid syntax


3.การใช้เลขนอกเหนือจากเลขฮินดูอารบิกเป็นค่าตัวเลข
ใน Python 2 นั้นหากจะแปลงสายอักขระที่เก็บตัวเลขให้เป็นข้อมูลชนิดจำนวนตัวเลขจะต้องใช้เลขฮินดูอารบิกเท่านั้น เช่น

โค้ด: เลือกทั้งหมด

int('20') # ได้ 20

แต่ใน Python 3 อาจใช้เลขไทยหรือเลขอื่นๆได้อีกหลายชนิด หรืออาจใช้ปนกันก็ได้ เช่น

โค้ด: เลือกทั้งหมด

int('๒๐') # ได้ 20

นอกจากเลขไทยแล้วยังใช้ตัวเลขของภาษาอื่นได้อีกหลายชนิด เช่น ลาว เขมร พม่า แต่ว่าเลขจีนไม่สามารถใช้ได้

4.ฟังก์ชัน print
ใน Python 2 คำสั่ง print มีโครงสร้างการใช้แบบนี้

โค้ด: เลือกทั้งหมด

print 'Mindphp'

คือ print แล้วเว้นวรรค ตามด้วยสิ่งที่ต้องการแสดงผลออกมา แต่ว่าใน Python 3 ได้ถูกเปลี่ยนกลายเป็นแบบนี้

โค้ด: เลือกทั้งหมด

print ('Mindphp')

จำเป็นที่นะต้องใส่วงเล็บครอบสิ่งที่ต้องการแสดงผลออกมา หากไม่ใส่ก็จะขัดข้องไม่สามารถรันได้ ความเปลี่ยนแปลงนี้มีความหมายมากถึงระดับโครงสร้าง เพราะใน Python 2 print ถือว่าเป็นแค่คำสั่งหนึ่ง ไม่ใช่ฟังก์ชัน จึงมีรูปแบบการทำงานคล้ายกับ for หรือ while คือใช้การจัดวางโดยอาจจะเว้นวรรคหรือใส่วงเล็บก็ได้

5.ฟังก์ชัน input
ใน Python 2 นั้นฟังก์ชัน input จะเป็นการใส่ข้อมูลที่เป็นตัวเลข แต่หากจะใส่สายอักขระต้องเป็น raw_input แต่ใน Python 3 ถูกแก้ให้ input เป็นการนำเข้าสายอักขระเท่านั้น และฟังก์ชัน raw_input ก็หายไป ไม่สามารถใช้ได้แล้ว
ยกตัวอย่าง เช่น

โค้ด: เลือกทั้งหมด

c = input()

เมื่อลองพิมพ์ข้อความใน Python 3 จะไม่มีอะไรเกิดขึ้น ค่าของสายอักขระเข้าไปเก็บในตัวแปร a ตามปกติ แต่ใน Python 2 จะขึ้นว่า

โค้ด: เลือกทั้งหมด

NameError: name 'ข้อความ' is not defined


6.การหารจำนวนเต็ม
ใน Python 2 นั้นจำนวนเต็มหารจำนวนเต็มจะได้จำนวนเต็มเช่นเดิม และหากเหลือเศษจะมีการปัดเศษให้เป็นจำนวนเต็ม
แต่ใน Python 3 จำนวนเต็มหารจำนวนเต็มจะได้จำนวนจริง ซึ่งมีทศนิยมได้ ดังนั้นจะไม่มีการปัดเศษ
ยกตัวอย่าง

โค้ด: เลือกทั้งหมด

print(5/3)

ใน Python 3 จะได้

โค้ด: เลือกทั้งหมด

1.6666666666666667

ส่วนใน Python 2 จะได้


7.การยกกำลังจำนวนติดลบ
ใน Python 2 หากจำนวนติดลบยกกำลังก็จะขัดข้องทันที ในขณะที่ใน Python 3 จะเปลี่ยนเป็นข้อมูลชนิดจำนวนเชิงซ้อนให้เลย เช่น

ใน Python 3 ได้

โค้ด: เลือกทั้งหมด

(-2.0386342710747223-0.6623924280875919j)

แต่ใน Python 2 ได้

โค้ด: เลือกทั้งหมด

ValueError: negative number cannot be raised to a fractional power


8.ชนิดข้อมูลของสายอักขระ
ใน Python 3 ชนิดของตัวอักษรที่เก็บอยู่ภายในสายอักขระนั้นทั้งหมดถูกเก็บในรูปแบบของ ยูนิโค้ด (unicode) ซึ่งสามารถเก็บตัวอักษรทั้งหมดทุกชนิดได้ในลักษณะเดียวกัน แต่ใน Python 2 อักษรถูกเก็บในรูปของ ASCII ส่วนอักษรที่ไม่ใช่อักษร ASCII ถูกเก็บในรูปของรหัสยูนิโค้ด utf-8
เมื่อลองใช้ฟังก์ชัน len เพื่อหาความยาวของสายอักขระที่มีอักษรที่ไม่ใช่ ASCII เปรียบเทียบกันระหว่างใน Python 2 กับ 3

โค้ด: เลือกทั้งหมด

print(len('mindpกขคงจ'))

ใน Python 3 จะได้ผลออกมาเป็น

ซึ่งก็เป็นไปตามที่เห็น เพราะความยาวของสายอักขระที่ใส่ลงไปเป็น 10 ตัวอักษร
แต่ถ้าเป็นใน Python 2 จะได้เป็น

ที่เป็นแบบนี้ทั้งๆที่มีอักษรแค่ 10 ตัวเท่านั้นก็ เพราะว่าใน Python 2 อักษรถูกเก็บในรูปของ ASCII อักษรที่ไม่ใช่ ASCII จะถูกเก็บในรูปของรหัสยูนิโค้ดซึ่งแต่ละอักษรก็ใช้จำนวนโค้ดแตกต่างกันออกไป

9.ชนิดข้อมูลของ range
หนึ่งในฟังก์ชันที่ถูกเปลี่ยนแปลงไปก็คือฟังก์ชัน range และมีฟังก์ชันหนึ่งที่หายไป นั่นก็คือ xrange ใน Python 2 นั้นมีฟังก์ชัน range กับ xrange ทั้ง 2 ฟังก์ชันแล้วคล้ายกันแต่มีความต่างกันเล็กน้อย
range เป็นฟังก์ชันสำหรับคืนค่าข้อมูลประเภทลิสต์ของจำนวนเต็มซึ่งมีค่าในช่วงตามที่กำหนดออกมา เช่น

โค้ด: เลือกทั้งหมด

print(range(10)) #จะได้ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

ถ้าลองหาชนิดของข้อมูล

โค้ด: เลือกทั้งหมด

print(type(range(10)) #จะได้ <type 'list'>

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

โค้ด: เลือกทั้งหมด

print(xrange(10))#จะได้ xrange(10)

xrange นั้นไม่ได้ให้ข้อมูลที่เป็นลิสต์ แต่เมื่อมันถูกเรียกใช้มันจะทำการสร้างข้อมูลตัวเลขเรียงขึ้นมาใหม่ ผลสุดท้ายจึงทำงานเหมือนเป็นลิสต์ ในการใช้งานนั้น เวลาที่สร้างตัวแปรขึ้นมานั้น xrange จะสร้างได้เร็วกว่าเพราะมันไม่ได้ทำการไล่สร้างลิสต์ขึ้นมาใหม่ในขณะนั้นเลย

10.การจัดการกับตัวแปรที่ใช้ใน for
ใน Python 3 เมื่อใช้คำสั่ง for สำหรับสร้างลิสต์ ตัวแปรนั้นจะถูกแยกออกเป็นคนละโลกกับตัวแปรภายนอก กล่าวคือต่อให้ชื่อตัวแปรซ้ำกันก็จะไม่กระทบต่อตัวแปรนั้นที่อยู่นอกคำสั่ง สร้างลิสต์ เช่น

โค้ด: เลือกทั้งหมด

i=10
print('ค่า i ก่อน for:', i)
print('ค่า i ใน for:', [i for i in range(5)])
print('ค่า i หลัง for:', i)

จะได้ผลลัพธ์เป็น

โค้ด: เลือกทั้งหมด

ค่า i ก่อน for: 10
ค่า i ใน for: [0, 1, 2, 3, 4]
ค่า i หลัง for: 10

เพราะ กรณีนี้ตัวแปร i ที่นิยามก่อนเริ่มใช้คำสั่ง for สร้างลิสต์ กับตัวแปร i ที่อยู่ในคำสั่งนั้นเป็นคนละตัวกัน ดังนั้นต่อให้สร้างลิสต์เสร็จค่า i ที่นิยามขึ้นก่อนหน้าก็ไม่มีการเปลี่ยนแปลง

11.เมธอด keys, values และ items ของดิกชันนารี
ใน Python 2 เมธอด keys, values และ items จะคืนค่าลิสต์ของคีย์, ค่า และ ทูเพิลของคีย์และค่า ตามลำดับ เช่น

โค้ด: เลือกทั้งหมด

dic = {'a': 1, 'b': 2, 'c': 3}
print(dic.keys())
print(dic.values())
print(dic.items())

ได้

โค้ด: เลือกทั้งหมด

['a', 'b', 'c']
[1, 2, 3]
[('a', 1), ('b', 2), ('c', 3)]

แต่ใน Python 3 จะคืนค่าของข้อมูลซึ่งเป็นตัวชี้ถึงค่าในดิกชันนารี โดยจะได้เป็นออบเจ็กต์ชนิด dict_keys, dict_values และ dict_items

โค้ด: เลือกทั้งหมด

dict_keys(['c', 'b', 'a'])
dict_values([3, 2, 1])
dict_items([('c', 3), ('b', 2), ('a', 1)])


12.ฟังก์ชัน map, filter และ zip

Python 2 นั้น ฟังก์ชัน map เมื่อใช้แล้วจะคืนค่าออกมาเป็นลิสต์ ไม่ว่าจะใส่ลิสต์หรือทูเพิลหรือเซ็ต

โค้ด: เลือกทั้งหมด

map(float,(1,2,3)) # ได้ [1.0, 2.0, 3.0]

แต่ใน Python 3 ฟังก์ชัน map จะให้ผลออกมาเป็นอิเทอเรเตอร์ ต้องนำมาแปลงเป็นลิสต์ต่ออีกทีจึงจะสามารถแสดงผลได้

โค้ด: เลือกทั้งหมด

map(float,(1,2,3)) # ได้ <map at 0x112383710>
list(map(float,(1,2,3))) # ได้ [1.0, 2.0, 3.0]

ฟังก์ชัน filter ใน Python 2 จะให้ผลเป็นลิสต์ถ้าใส่ลิสต์หรือเซ็ตเข้าไป และให้ผลเป็นทูเพิลถ้าใส่เป็นทูเพิล

โค้ด: เลือกทั้งหมด

filter(lambda x:x%2,[1,2,3]) # ได้ [1, 3]
filter(lambda x:x%2==0,(1,2,3)) # ได้ (2,)
filter(lambda x:x<3,{1,2,3}) # ได้ [1, 2]

แต่ Python 3 จะให้ผลเป็นอิเทอเรเตอร์เสมอ ไม่ว่าจะใส่อะไร ต้องมาแปลงอีกที

โค้ด: เลือกทั้งหมด

filter(lambda x:x<3,{1,2,3}) # ได้ <filter at 0x112383eb8>
set(filter(lambda x:x<3,{1,2,3})) # ได้ {1, 2}

ฟังก์ชัน zip ใน Python 2 จะให้ผลเป็นลิสต์ของทูเพิล

โค้ด: เลือกทั้งหมด

zip({1,2},{3,4}) # ได้ [(1, 3), (2, 4)]
zip([1,2,3],[4,5,6]) # ได้ [(1, 4), (2, 5), (3, 6)]

แต่ใน Python 3 จะได้ผลเป็นอิเทอเรเตอร์ทั้งหมด พอแปลงเป็นลิสต์แล้วจึงจะได้ผลเหมือนใน Python 2

โค้ด: เลือกทั้งหมด

zip({1,2},{3,4}) # ได้ <zip at 0x11239e188>
list(zip([1,2,3],[4,5,6])) # ได้ [(1, 4), (2, 5), (3, 6)]


13.การใช้ฟังก์ชัน super
ใน Python 2 เวลาที่จะประกาศเรียกใช้ฟังก์ชัน super จากในซับคลาสเพื่อเรียกซูเปอร์คลาสจะมีกฏ

โค้ด: เลือกทั้งหมด

class test(object):
     def __init__(self,x):
         self.x = x
class test(stest):
     def __init__(self,x,y):
         super(test,self).__init__(x)
         self.y = y
c = test(5,10)

จะเห็นว่าตอนที่ประกาศคลาสหลักจำเป็นต้องมี (object) อยู่ด้านหลัง และในฟังก์ชัน super ต้องใส่อาร์กิวเมนต์ 2 ตัว เป็นตัวคลาสและตัวอินสแตนซ์
แต่ใน Python 3 สามารถละได้ทั้งหมด จึงเขียนแค่นี้ได้

โค้ด: เลือกทั้งหมด

class stest:
     def __init__(self,x):
         self.x = x
class test(stest):
     def __init__(self,x,y):
         super().__init__(x)
         self.y = y
c = test(5,10)

แต่จะเขียนเต็มๆแบบ Python 2 ก็ไม่ผิด สามารถเขียนได้เช่นกัน

14.ออบเจ็กต์ของความผิดพลาดในโครงสร้าง try except
ใน Python 2 เวลาที่ใช้ except หากต้องการให้มีตัวแปรมารับออบเจ็กต์ของความผิดพลาดเพื่อนำไปแสดงผลหรือทำอะไรจะใช้จุลภาค , เขียนต่อจากชนิดของข้อผิดพลาดไปเลย

โค้ด: เลือกทั้งหมด

import math
try:
     1/0
except Exception, er:

     print(type(er))

     print(er)
     # จะได้ <type 'exceptions.ZeroDivisionError'> integer division or modulo by zero
     

แต่ใน Python 3 จะใช้ as แทน นอกจากนี้ก็จะเห็นว่าข้อความที่แสดงตอนมีข้อผิดพลาดก็อาจต่างกันด้วย

โค้ด: เลือกทั้งหมด

import math
try:
    1/0
except Exception as er:
    print(type(er))
    print(er)
     # จะได้ ]<class 'ZeroDivisionError'> division by zero
   


15.เมธอด next กับ __next__
นิยามคลาสของอิเทอเรเตอร์นั้นภายในโครงสร้างจะต้องนิยามเมธอดที่จะให้ทำงานเมื่อเจอฟังก์ชัน next ซึ่งเมธอดนั้นใน Python 2 มีชื่อว่า next

โค้ด: เลือกทั้งหมด

class test:
     def __init__(self):
         self.n = 0
     def __iter__(self):
         return self
     def next(self):
         self.n += 1
     return self.n

แต่ใน Python 3 เมธอดนี้จะชื่อว่า __next__

โค้ด: เลือกทั้งหมด

class test:
     def __init__(self):
         self.n = 0
     def __iter__(self):
         return self
     def __next__(self):
         self.n += 1
     return self.n

เมธอดจะถูกเปลี่ยนชื่อมีแค่ next เท่านั้น

16.มอดูล __future__
Python 2 สามารถนำคำสั่งบางอย่างจาก Python 3 มาใช้ได้โดยการนำเข้ามอดูล __future__ เช่น

โค้ด: เลือกทั้งหมด

from __future__ import print_function
print 5
# จะได้ SyntaxError: invalid syntax

จะไม่สามารถใช้เว้นช่อง ต้องใส่วงเล็บแบบใน Python 3 เลขจะเรียงต่อกันแทนที่จะออกมาเป็นทูเพิล

โค้ด: เลือกทั้งหมด

print(5,5,5,5)
# จะได้ 5 5 5 5
รูปภาพ

ย้อนกลับไปยัง

ผู้ใช้งานขณะนี้

กำลังดูบอร์ดนี้: 4 และ บุคคลทั่วไป 0 ท่าน