อ๊อบเจ็กและคลาส

  • warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 1005 is not allowed to access /tmp owned by uid 0 in /var/www/sites/sugree/codenone.com/subdomains/www/html/includes/file.inc on line 190.
  • warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 1005 is not allowed to access /tmp owned by uid 0 in /var/www/sites/sugree/codenone.com/subdomains/www/html/includes/file.inc on line 190.

หนึ่งในคุณสมบติที่ดีที่สุดของไพธอนก็คือ คลาส (Class) นี่เอง คลาสเป็นความสามารถที่แถมมากับหลักการ Object-Oriented Programming ซึ่งเหมาะกับการพัฒนาโปรแกรมทั้งขนาดเล็ก ขนาดกลาง และขนาดใหญ่ มีจุดเด่นที่น่าสนใจของคลาสก็คือ การแบ่งปัญหาใหญ่ให้เล็กลงเพื่อแก้ไขในขอบเขตที่จำกัด ทั้งยังช่วยให้การทดสอบง่ายขึ้นอีกด้วย

อย่างไรก็ตามคลาสในไพธอนไม่ตรงตามหลักการของ OOP มากนัก ดังนั้นไพธอนอาจเหมาะเป็นภาษาแรก แต่ไม่เหมาะสำหรับการสอน OOP แน่ๆ

กลับมาดูคลาสในไพธอนดีกว่า เริ่มจากคลาสง่ายๆ

class Person:
    pass

ตัวอย่างข้างบนเป็นคลาสที่พื้นฐานที่สุด ขณะเดียวกันก็สามารถนำไปประยุกต์ใช้งานได้มากมาย ก่อนอื่นต้องสร้างอ๊อบเจ็กขึ้นมาก่อน

p = Person()

แค่นี้ก็เอา p ไปใช้ได้แล้ว ซึ่งตอนนี้มีสภาพเหมือนกล่องเปล่า อยากใส่อะไรก็ได้

p.name = 'Alice'
p.age = 8
 
print p.name,p.age

อย่างไรก็ตามการใช้งานแบบข้างบนจะมีข้อเสียนิดหน่อย ตรงที่อ๊อบเจ็กอื่นของคลาส Person จะไม่มี name และ age ซึ่งแก้ไขได้โดยการกำหนดค่าเริ่มต้น

class Person:
    name = 'noname'
    age = 0

ซึ่งจะรับประกันได้ว่า Person ทุกอ็อบเจ็กจะมี name และ age เสมอ แต่ยังไม่สามารถกำหนดค่าเริ่มต้นแบบสวยๆ ได้

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

วิธีกำหนดค่าเริ่มต้นจะต้องใช้ constructor เข้ามาช่วย ในไพธอนนั้นจะเป็นเมธอดชื่อ __init__ นั่นเอง ทุกเมธอดในคลาสของไพธอนจะใช้พารามิเตอร์ตัวแรกแทนตัวเอง ซึ่งปกติจะใช้ชื่อ self สำหรับคนที่ชินกับภาษาซี หรือจาวา self ก็คือ this นี่เอง วิธีแบบนี้ทำให้การเขียนโปรแกรมเข้าใจง่ายขึ้นมาก เพราะไม่ต้องงงว่า this คืออะไร มีที่มาอย่างไร เวลาใช้จึงเปลี่ยนไปเล็กน้อย

p = Person('Alice',8)

ถ้าอยากใส่เมธอดเพิ่มเติมก็ใส่เข้าไปในคลาสได้

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
 
    def show(self):
        print '%s is %d years old.' % (self.name,self.age)
 
p = Person('Alice',8)
p.show()

หรือถ้าจะให้ดูเป็นไพธอนมากกว่านี้ก็ต้องแก้ constructor นิดนึง

class Person:
    def __init__(self,**kw):
        self.name = kw.get('name','noname')
        self.age = kw.get('age',0)
 
    def show(self):
        print '%s is %d years old.' % (self.name,self.age)
 
p = Person(name='Alice',age=8)
p.show()

หรือจะเป็นแบบข้างล่างก็ได้

class Person:
    name = 'noname'
    age = 0
 
    def __init__(self,**kw):
        self.__dict__.update(kw)
 
    def show(self):
        print '%s is %d years old.' % (self.name,self.age)
 
p = Person(name='Alice',age=8)
p.show()
veer's picture

class ใน python ไม่ตรงตามหลัก OOP ตรงไหนอะครับ? เข้าถึง attribute ง่ายเกินไป?

omni_kh's picture

ผมมองว่าไม่ใช่ class นะ แต่เป็น object ต่างหาก เพราะว่าไม่มี information hiding เลย ใครจะล้วงเอาอะไรไป หรือลบ attribute ของ object ก็ได้ เช่น

>>> class Person2:
...     def __init__(self):
...             self.name = "me"
...
>>> p = Person2()
>>> p.name
'me'
>>> del p.name
>>> p.name
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: Person2 instance has no attribute 'name'

นอกจากนั้นถ้าเราสร้างคลาสแบบนี้

>>> class Person:
...     name = "me"
...     age = 20

เวลาสร้าง object นั้น attribute name จะไม่ใช่ของ person จริงจนกว่าจะ assign ค่าให้มัน และพอลบ attribute แล้วก็ยังสามารถอ้างไปถึง attribute ของ class ได้อีก

>>> p = Person()
>>> p.name
'me'
>>> del p.name
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: Person instance has no attribute 'name'
>>> p.name = "hello"
>>> p.name
'hello'
>>> del p.name
>>> p.name
'me'

มันเลยดูงงๆ นิดหน่อย แต่ถ้าเขียน code ดีๆ ตาม convention ก็จะไม่งงนะครับ

แถมคำถามหน่อย...
เวลา define class นี่ควรใช้แบบ Person หรือแบบ Person2 (แบบที่ไม่ใช้ __init__ กับแบบที่ใช้ __init__ ตามลำดับ) ดีครับ?

ย้าย Codenone

ประกาศย้าย Codenone ไปใช้ Forum ของ Blognone แทนครับ ตามไปตั้งกระทู้ต่อได้ที่ Codenone Forum (รายละเอียดอ่านจากกระทู้ ย้าย Codenone ไปรวมกับ Blognone)

กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น