Lập Trình Hướng Đối Tượng Trong Python

2015/07/20

Bài viết tập trung các thủ thuật khi sử dụng kỹ thuật Hướng Đối Tượng trong Python. Thực ra trong Python, các khái niệm về hướng đối tượng đã được giản lược nhiều. Thêm vào đó, lại không có những khái niệm phức tạp như access modifier, destructor, … Việc xây dựng các class cũng vì thế đơn giản hơn.

Enum trong python

Sử dụng lớp được cài đặt trong thư viện cung cấp sẵn:

from enum import Enum

class Color(Enum):
    RED     = 1
    GREEN   = 2
    BLUE    = 3

Không multiple constructors

Nhưng ta có thể sử dụng optical argument như một thế mạnh và thay thế cho multiple constructor.

Không access modifier

Đồng nghĩa với việc không có public, private hay là protected gì cả. Ngay cả việc thêm __ vào trước properties hay method cũng không giải quyết được vấn đề. Với mỗi thuộc tính __p của lớp A đơn giản là được đổi tên thành _A__p.

Private methods

Sử dụng tiền tố __ khác các phương thức muốn đặt private.

Tạo property

Nếu được, tạo thành method thay thế. Còn không có thể sử dụng decorator @property trước method để đổi thành property.

Đa kế thừa

Tránh vấn đề này càng tốt. Tham khảo tại đây.

Các thuộc tính và method static

Mình không nghĩ là cần thuộc tính hay method static cho lắm. Nếu có thể cài thuộc tính/method static thì thay vào đó có thể đặt bên ngoài class và xếp trong cùng module. Nhưng vậy có thể truy cập các thuộc tính, hàm thông qua module thay vì class, và mình thấy hầu như không khác nhau là mấy.

Gọi constructor từ lớp cha

Đây là một vấn đề khá nan giải trong trường hợp đa kế thừa. Giả sử ta có lớp A, lớp B và C. Trong đó lớp C kế thừa vừa lớp A và lớp B. Vấn đề là làm thế nào để gọi A, B trong hàm khởi tạo, và làm thế nào để biết lớp cha nào được gọi trước.

class A(object):
    def __init__(self):
        super(A, self).__init__()
        print "entering A"
        print "leaving A"

class B(object):
    def __init__(self):
        super(B, self).__init__()
        print "entering B"
        print "leaving B"

class C(A,B):
    def __init__(self):
        print "entering c"
        super(C, self).__init__()
        print "leaving c"


if __name__ == '__main__':
    c = C()

Có một số điều khá thú vị xoay quanh điều này sau khi ta thử nghiệm hoán vị trình tự kế thừa, trình tự định nghĩa lớp:

  1. Trong mỗi hàm phải khai báo super(ClassName, self).__init__() thì việc gọi các hàm khởi tạo từ các lớp cha mới thực hiện được.
  2. Không phụ thuộc vào trình tự kế thừa.
  3. Trình tự hàm khởi tạo được gọi dựa them alphabet.

Practices

  1. Để kiểm tra một biến có phải là 1 thể hiện của lớp không, sử dụng hàm isinstance, tuy nhiên khuyến khích không xài. Vì Python là Duck Type mà.
  2. Khai báo một thứ na ná struct trong C/C++: {% highlight python %} class ClassName: pass {% endhighlight%}

Sau đó thì có thể tha hồ thêm thuộc tính nào vào cũng được.

References

  1. https://docs.python.org/2/tutorial/classes.html

P.s: Các chủ đề hại não và nâng cao có thể được đề cập là Iterators, Generators, …