Instance, class, static method trong Python
Trong bài hướng dẫn này, mình sẽ giúp làm sáng tỏ về 3 loại phương thức trong Python: Instance, Class và Static method.
Nếu bạn thực sự hiểu được sự khác biệt giữa chúng, bạn sẽ có thể HỌC PYTHONtốt hơn, truyền đạt ý định của nó rõ ràng hơn và sẽ dễ dàng bảo trì trong thời gian dài.
Tổng quan về Instance, Class và Static Method trong Python
Hãy bắt đầu tìm hiểu về instance method, class method và static method bằng cách viết một [Python 3] class mà có ví dụ đơn giản cho cả 3 loại phương thức này:
class MyClass: def method[self]: return 'instance method', self @classmethod def classmethod[cls]: return 'class method', cls @staticmethod def staticmethod[]: return 'static method'
Lưu ý cho Python 2: Decorator @staticmethod và @classmethod có sẵn kể từ Python 2.4 và ví dụ này sẽ hoạt động như bình thường. Thay vì sử dụng một khai báo class MyClass:, bạn có thể chọn khai báo một class kiểu mới kế thừa từ đối tượng với cú phápclass MyClass [object]:.
Instance Method trong Python là gì?
Phương thức đầu tiên trên MyClass, được gọi là method, là một phương thứcinstance method[phương thức thể hiện] thông thường.
Đó là loại phương thức cơ bản, không rườm rà thường được sử dụng nhất.
Bạn có thể thấy phương thức lấy một tham số, self, nó trỏ đến một thể hiện của MyClass khi phương thức được gọi [nhưng tất nhiên các phương thức thể hiện có thể chấp nhận nhiều hơn một tham số].
Thông qua tham số self, các phương thức thể hiện có thể tự do truy cập các thuộc tính và các phương thức khác trên cùng một đối tượng.
Điều này mang lại cho chúng rất nhiều sức mạnh khi sửa đổi trạng thái đối tượng.
Chúng không chỉ có thể sửa đổi trạng thái đối tượng, các instance method cũng có thể truy cập vào chính class đó thông qua thuộc tính self.__ class__.
Điều này có nghĩa là các instance method cũng có thể sửa đổi trạng thái của class.
Class Method trong Python là gì?
Hãy so sánh với phương thứ thứ hai, MyClass.classmethod. Mình đã đánh dấu phương thức này bằng một Decorator là @classmethod để gắn cờ nó là một class method.
Thay vì chấp nhận một tham số self, các class method lấy tham số cls trỏ đến class, và không phải là đối tượng thể hiện, khi phương thức được gọi.
Bởi vì class method chỉ có quyền truy cập vào đối số cls này, nên nó có thể sửa đổi trạng thái đối tượng.
Điều đó sẽ yêu cầu quyền truy cập vào self. Tuy nhiên, các class method vẫn có thể sửa đổi trạng thái class áp dụng trên tất cả các phiên bản của class.
Static Method trong Python là gì?
Phương thức thứ ba, MyClass.staticmethod được đánh dấu bằng Decorator là @staticmethod để gắn cờ chó biết nó là một Static method.
Kiểu phương thức này không có tham số self hay tham số cls [nhưng tất nhiên, nó có thể nhận số lượng tham số khác tùy ý].
Do đó, một Static method không thể sửa đổi trạng thái đối tượng cũng như trạng thái class.
Các Static method bị hạn chế truy cập một số dữ liệu - và chúng chủ yếu là một cách để thiết lập namespace các phương thức của bạn.
Hoạt động của instance, class và static method
Tôi biết cho đến đoạn nãy, đã khá đủ lý thuyết.
Mà quan trọng nhất để hiểu 3 loại phương thức này chúng ta phải đi vào trực quan. Dưới đây sẽ là một số ví dụ cụ thể để bạn thấy cách chúng hoạt động.
Hãy xem cách các phương thức này hoạt động khi chúng ta gọi chúng. Chúng ta sẽ bắt đầu bằng cách tạo một thể hiện của class và sau đó gọi ba phương thức khác nhau trên đó.
MyClass được thiết lập theo cách mà mỗi khai triển của từng phương thức lại trả về một tuple chứa thông tin để chúng ta theo dõi những gì diễn ra - và phần nào của class hoặc đối tượng mà phương thức có thể truy cập.
- Tham khảo: Các kiễudữ liệu trong Python
Ở đây, những gì xảy ra khi chúng ta gọi một instance method:
obj = MyClass[] print[obj.method[]] #Kết quả ['instance method', ]
Điều này đã xác nhận rằng method [instance method] có quyền truy cập vào instance object [được in dưới dạng] thông qua đối số slef.
Khi phương thức được gọi, Python thay thế đối số self bằng instance object làobj.
Chúng ta có thể bỏ qua cú pháp [obj.method[]] và truyền instance object theo cách thủ công để có được kết quả tương tự:
obj = MyClass[] print[MyClass.method[obj]] #Kết quả ['instance method', ]
Bạn có thể đoán điều gì sẽ xảy ra nếu bạn cố gọi phương thức mà không tạo instance trước không?
Nhân tiện, các instance method cũng có thể truy cập vào chính class đó thông qua thuộc tính self.__ class__.
Điều này làm cho các instance method trở nên mạnh mẽ về các hạn chế truy cập - chúng có thể sửa đổi trạng thái trên instance object và trên chính class đó.
Hãy thử gọi phương thức tiếp theo xem nào:
obj = MyClass[] print[obj.classmethod[]] #Kết quả ['class method', ]
Việc gọi classmethod[] cho chúng ta thấy nó không có quyền truy cập vào đối tượng, nhưng chỉ với đối tượng, đại diện cho chính class đó [mọi thứ trong Python là một đối tượng, ngay cả chính các class].
Lưu ý cách Python tự động chuyển class làm đối số đầu tiên cho hàm khi chúng ta gọi MyClass.classmethod[].
Gọi một phương thức trong Python thông qua cú pháp dấu chấm kích hoạt hành vi này. Tham số self trên các instance method hoạt động theo cùng một cách.
Xin lưu ý rằng việc tự đặt tên cho các tham số này làself và clscũng chỉ là quy ước.
Bạn có thể dễ dàng đặt tên cho chúng là the_object và the_group và nhận được kết quả tương tự. Bởi vì Python đã định vị tham số này là tham số đầu tiên trong phương thức.
Bây giờ chúng ta thử gọi static method:
obj = MyClass[] print[obj.staticmethod[]] #Kết quả static method
Bạn có thấy cách chúng ta gọi staticmethod[] trên đối tượng và có thể thực hiện thành công không?
Một số lập trình viên ngạc nhiên khi họ biết rằng nó có thể gọi một phương thức tĩnh trên một instance object.
Thực ra, Python chỉ thực thi các hạn chế truy cập bằng cách không truyền vào đối số self hoặc cls khi một static method được gọi bằng cú pháp dấu chấm.
Bây giờ, hãy xem điều gì xảy ra khi chúng ta cố gắng gọi các phương thức này trên chính class đó - mà không tạo ra một instance object trước đó:
print[MyClass.classmethod[]] #Kết quả: ['class method', ] print[MyClass.staticmethod[]] #Kết quả: static method print[MyClass.method[]] #Kết quả: TypeError: method[] missing 1 required positional argument: 'self'
Chúng ta có thể gọi classmethod[] và staticmethod[], nhưng cố gắng gọi instance medthod method[] sẽ gây ra lỗi.
Lần này chúng ta đã không tạo ra một instance object và đã thử gọi một instance function trực tiếp trên bản thiết kế của class.
Điều này có nghĩa là không có cách nào để Python đưa ra đối số self và do đó nó thất bại.
Điều này sẽ làm cho bạn thấy sự khác biệt giữa ba loại phương thức này rõ ràng hơn một chút. Nhưng mình sẽ không dừng tại đây.
Trong hai phần tiếp theo, chúng ta sẽ đi qua hai ví dụ thực tế hơn một chút để sử dụng các loại phương thức đặc biệt này.
Mình sẽ dựa trên các ví dụ của mình xung quanh class Pizza này:
class Pizza: def __init__[self, ingredients]: self.ingredients = ingredients def __repr__[self]: return f'Pizza[{self.ingredients!r}]' Pizza[['cheese', 'tomatoes']] Pizza[['cheese', 'tomatoes']]
Lưu ý:Ví dụ này và các ví dụ khác trong hướng dẫn sử dụng trên phiên bản 3.6 trở đi để xây dựng chuỗi được trả về bởi __repr__. Trên Python 2 và các phiên bản Python 3 trước 3.6, bạn sử dụng một biểu thức định dạng chuỗi khác nhau, ví dụ:
def __repr__[self]: return 'Pizza[%r]' % self.ingredients