Toidicode.com

Toidicode.com

BASIC TO ADVANCE

Bài 4: Phạm vi truy cập thuộc tính và phương thức trong Python OOP

Bài trước mình đã giới thiệu với mọi người về kế thừa class trong Python rồi, Và ở phần đó mình có nói "Khi một class con kế thừa từ một class cha thì nó sẽ sử dụng được toàn bộ các thành phần được cho phép trong class cha" Vậy hôm nay chúng ta sẽ cùng đi tìm hiểu cụm từ được cho phép này là gì nhé!

1, Phạm vi truy cập thuộc tính và phương thức.

Như ở phần Học Python cơ bản mình cũng có giới thiệu với mọi người là biến trong lập trình Python thì có 2 loại là biến cục bộ và biến toàn cục đúng không ạ?

Nhưng đó là với biến, ở đây trong lập trình hướng đối tượng nói chung và lập trình Python nói riêng thì các thành phần trong một đối tượng sẽ tồn tại ở 3 mức độ khác nhau là public, protected, private. 3 mức độ này cũng đại diện cho tính chất đóng gói của hướng đối tượng, còn đóng gói như nào thì hãy cùng tìm hiểu về các mức độ này...

2, Public.

-Public là trạng thái công khai nhất trong ba mức độ, khi một thành phần trong class được khai báo ở dạng public tức là chúng ta có thể sử dụng được thành phần đó từ bất kỳ đâu trong chương trình. Và để khai báo một thành phần trong class là public thì mọi người chỉ cần tuân thủ quy tắc sau:

Tên của thành phần không được bắt đầu bằng ký tự _ mà phải bắt đầu bằng chữ cái.

 VD: Mình sẽ khai báo một thuộc tính và một phương thức ở dạng public và gọi nó ở các trường hợp khác nhau:

class Foo:
    # Khai báo thuộc tính ở dạng public
    name = "Foo"
    # Khai báo phương thức ở dạng public
    def getName(self):
        # gọi thành phần trong class
        print(self.name)

# gọi thành phần ngoài class
print(Foo().name) # Foo
Foo().getName() # Foo

class Bar(Foo):
    pass

#test
Bar().getName() # Foo

Như các bạn đã thấy, khi một thành phần là public thì nó sẽ gọi được trong mọi nơi.

2, Protected.

Protected nằm ở mức độ thứ 2. Khi một thành phần trong class được khai báo là protected thì nó chỉ có phạm vi sử dụng ở trong class khởi tạo nó và class kế thừa từ class đó (class con) mà chúng ta sẽ không thể gọi được khi đứng từ bên ngoài class.

Nhưng, bản chất trong Python không tồn tại loại phạm vi này, do đó chúng ta quy chuẩn nó về protected mà bản chất của nó vẫn là public.

Để khai báo một thành phần là protected thì mọi người cần tuân theo quy tắc sau:

Tên của thành phần phải được bắt đầu bằng 1 ký tự _.

VD:  Mình sẽ thay đổi các thuộc tính và phương thức ở VD trên thành protected và gọi nó ở các trường hợp khác nhau (lưu ý đây chỉ là quy chuẩn còn thực chất trong Python thì nó vẫn được coi là public).

class Foo:
    # Khai báo thuộc tính ở chuẩn protected
    _name = "Foo"
    # Khai báo phương thức ở chuẩn protected
    def _getName(self):
        # gọi thành phần trong class
        print(self._name)

# gọi thành phần ngoài class
print(Foo()._name) # Foo
Foo()._getName() # Foo

class Bar(Foo):
    pass

#test
Bar()._getName() # Foo

Như các bạn đã thấy thì nó hoàn toàn giống như public đúng không! Mình nhắc lại, mức độ này trong Python chỉ mang tính chất quy chuẩn còn thực sự thì nó vẫn là public.

3, Private.

Private là phạm vị hẹp nhất trong lập trình hướng đối tượng, khi một thành phần trong đối tượng được khai báo ở dạng private, thì nó chỉ có phạm vi hoạt động ở trong class khai báo nó mà thôi.

Để khai báo một thành phần ở dạng private thì mọi người chỉ việc tuân thủ theo quy tắc sau:

Tên cả thành phần phải được bắt đầu bằng 2 ký tự __.

VD: Mình sẽ thay đổi thuộc tính và phương thức ở trong VD trên về dạng private.

class Foo:
    # Khai báo thuộc tính ở chuẩn private
    __name = "Foo"
    # Khai báo phương thức ở chuẩn private
    def __getName(self):
        # gọi thành phần trong class
        print(self.__name)
    # khai báo một phương thức ở dạng public để gọi thành phần private
    def get(self):
        self.__getName()

# gọi thành phần ngoài class
print(Foo().__name) # 'Foo' object has no attribute '__name'
Foo().__getName() # 'Foo' object has no attribute '__getName'
Foo().get() # Foo

class Bar(Foo):
    def getNameinFoo(self):
        self.__getName()

#test
Bar().getNameinFoo() # 'Bar' object has no attribute '_Bar__getName'

5, Lời kết.

Như vậy phần này mình đã giới thiệu với mọi người về các mức truy cập của một thành phần trong đối tượng rồi. Tuy rằng nó có hơi khác so với số đông các ngôn ngữ hiện nay một chút nhưng chuẩn này thì cũng không quá khó nhớ đúng không mọi người!

Đăng ký nhận tin.

Chúng tôi chỉ gửi tối đa 2 lần trên 1 tháng. Tuyên bố không spam mail!

Vũ Thanh Tài

About author
The best way to learn is to share
Xem tất cả bài đăng

3 Comments

em chào anh, e mong anh sẽ giải đáp thắc mắc này giúp em ạ
e thấy có 1 số lib trong đó chỉ cho phép gọi từ class ạ
vd: numpy
e chỉ có thể gọi np.concatenate()

nguyen huu huy

3 năm trước

mà e lại k thể gọi obj.concatenate()
e cũng muốn viết 1 method chỉ cho phép gọi từ class thì e nên xử lý như nào vậy ạ ?
e mong anh sẽ giải đáp và cho e xin từ khóa để e có thể tìm kiếm ạ

nguyen huu huy

3 năm trước

Chào nguyen huu huy,

Đó là static method nhé bạn,

Bạn có thể tham khảo link: https://www.geeksforgeeks.org/class-method-vs-static-method-python/

Vũ Thanh Tài

3 năm trước

Bình luận

Captcha