Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Tìm hiểu về Methods trong Python
Trong bài viết này, bạn sẽ tìm hiểu về các phương thức (methods) trong Python, cách chúng hoạt động, và sự khác biệt giữa phương thức và hàm. Phương thức là một khái niệm quan trọng trong lập trình hướng đối tượng, giúp bạn thao tác với các đối tượng và làm việc với các lớp một cách hiệu quả hơn. Qua đó, bạn sẽ hiểu rõ hơn cách Python tự động quản lý và truyền đối tượng trong các phương thức, cũng như cách sử dụng self
để truy cập đối tượng bên trong lớp.
Giới thiệu về phương thức (methods) trong Python
Theo định nghĩa, một phương thức là một hàm được liên kết với một thể hiện của một lớp (class). Trong bài hướng dẫn này, bạn sẽ hiểu cách phương thức hoạt động bên dưới lớp.
Hãy xem ví dụ về lớp Request
chứa hàm send()
dưới đây:
class Request: def send(): print('Đã gửi')
Bạn có thể gọi hàm send()
thông qua lớp Request
như sau:
Bài viết này được đăng tại [free tuts .net]
Request.send() # Đã gửi
Hàm send()
ở đây là một đối tượng hàm (function object), tức là một thể hiện của lớp function
, như bạn có thể thấy qua đầu ra sau:
print(Request.send)
Kết quả:
<function Request.send at 0x00000276F9E00310>
Kiểu của send
là một hàm:
print(type(Request.send)) # <class 'function'>
Phương thức ràng buộc với một đối tượng trong Python
Giờ hãy tạo một thể hiện mới của lớp Request
:
http_request = Request()
Nếu bạn hiển thị http_request.send
, bạn sẽ nhận được một đối tượng phương thức ràng buộc (bound method object):
print(http_request.send)
Kết quả:
<bound method Request.send of <__main__.Request object at 0x00000104B6C3D580>>
Do đó, http_request.send
không phải là một hàm như Request.send
. Kiểm tra xem hai đối tượng này có giống nhau hay không sẽ trả về False
như mong đợi:
print(type(Request.send) is type(http_request.send)) # False
Lý do là kiểu của Request.send
là function
, trong khi kiểu của http_request.send
là method
:
print(type(http_request.send)) # <class 'method'> print(type(Request.send)) # <class 'function'>
Như vậy, khi bạn định nghĩa một hàm bên trong một lớp, nó chỉ là một hàm. Tuy nhiên, khi bạn truy cập hàm đó thông qua một đối tượng, hàm sẽ trở thành một phương thức.
Do đó, một phương thức là một hàm được ràng buộc với một thể hiện của lớp.
Cách phương thức hoạt động
Nếu bạn gọi phương thức send()
thông qua đối tượng http_request
, bạn sẽ gặp lỗi TypeError
như sau:
http_request.send()
Lỗi:
TypeError: send() takes 0 positional arguments but 1 was given
Nguyên nhân là vì khi bạn gọi một phương thức qua đối tượng, Python sẽ tự động truyền đối tượng đó vào phương thức dưới dạng đối số đầu tiên.
Hãy định nghĩa lại lớp Request
để phương thức send()
chấp nhận danh sách đối số:
class Request: def send(*args): print('Đã gửi', args)
Nếu bạn gọi phương thức send()
từ lớp Request
, danh sách đối số sẽ trống:
Request.send() # Đã gửi ()
Tuy nhiên, khi gọi từ một thể hiện của lớp, danh sách đối số sẽ không trống:
http_request.send() # Đã gửi (<__main__.Request object at 0x000001374AF4D580>,)
Trong trường hợp này, đối tượng http_request
đã được truyền vào như là đối số đầu tiên của phương thức send()
.
Bạn có thể kiểm tra xem đối tượng được truyền vào có giống với đối tượng gọi phương thức không:
print(hex(id(http_request))) # In địa chỉ bộ nhớ của đối tượng http_request.send()
Kết quả:
0x1ee3a74d580 Đã gửi (<__main__.Request object at 0x000001EE3A74D580>,)
Địa chỉ bộ nhớ của đối tượng http_request
giống với đối tượng được truyền vào phương thức send()
.
Tên gọi self
trong Python
Như vậy, phương thức của một đối tượng luôn có đối tượng đó làm đối số đầu tiên. Theo quy ước, đối số này được gọi là self
:
class Request: def send(self): print('Đã gửi', self)
Nếu bạn từng làm việc với các ngôn ngữ lập trình khác như Java hay C#, self
tương tự như this
trong các ngôn ngữ đó.