Các phương thức lớp của Wikipedia là gì


37

Đã có một cuộc thảo luận trong trò chuyện liên quan đến một câu hỏi (bản thân câu hỏi không liên quan đến câu hỏi này), điều đó đã tiết lộ tôi có thể không biết Python gì.

Trong tâm trí của tôi, mặc dù thuật ngữ khác nhau giữa các ngôn ngữ, chúng ta thường có thể phân loại các chức năng là:

  • chức năng [miễn phí]
  • phương thức tĩnh / hàm thành viên tĩnh
  • phương thức không tĩnh / hàm thành viên không tĩnh

Rõ ràng trong Python có một loại hàm khác không phù hợp với các loại trên, đó là một phương thức nhưng "không biết lớp của nó".

"Phương thức lớp" và "phương thức cá thể" trong Python là gì?


1
Nếu bất kỳ ai quan tâm đến các cuộc thảo luận trò chuyện, hãy bắt đầu ở đây: chat.stackexchange.com/transcript/message/26479002#26479002
Yannis

1
IMO một câu trả lời tốt hơn được cung cấp bởi một trang web stackexchange khác: stackoverflow.com/questions/136097/
Trevor Boyd Smith

FYI liên kết được cung cấp ở dưới cùng được chấp nhận ... nhưng tôi nghĩ nhiều người sẽ bỏ lỡ liên kết hoặc không bao giờ truy cập được và vì vậy tôi đã sao chép nó lên đây.
Trevor Boyd Smith

Câu trả lời:


49

Câu trả lời ngắn

  • một phương thức cá thể biết cá thể của nó (và từ đó, lớp của nó)
  • một phương thức lớp biết lớp của nó
  • một phương thức tĩnh không biết lớp hoặc thể hiện của nó

Câu trả lời dài

Phương thức lớp

Một phương thức lớp là một phương thức thuộc về toàn bộ lớp. Nó không yêu cầu một ví dụ. Thay vào đó, lớp sẽ tự động được gửi làm đối số đầu tiên. Một phương thức lớp được khai báo với trình @classmethodtrang trí.

Ví dụ:

class Foo(object):
    @classmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)
Foo.hello()
-> "Hello from Foo"
Foo().hello()
-> "Hello from Foo"

Phương pháp sơ thẩm

Mặt khác, một phương thức cá thể yêu cầu một thể hiện để gọi nó và không yêu cầu trang trí. Đây là loại phương pháp phổ biến nhất.

class Foo(object):
    def hello(self):
        print("hello from %s" % self.__class__.__name__)
Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'self'

(lưu ý: ở trên là với python3; với python2 bạn sẽ gặp một lỗi hơi khác)

Phương thức tĩnh

Một phương thức tĩnh tương tự như một phương thức lớp, nhưng sẽ không lấy đối tượng lớp làm tham số tự động. Nó được tạo ra bằng cách sử dụng @staticmethodtrang trí.

class Foo(object):
    @staticmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)

Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'cls'

Liên kết tài liệu

Dưới đây là các liên kết đến tài liệu python3 có liên quan:

Tài liệu mô hình dữ liệu có điều này để nói về sự khác biệt giữa các phương thức lớp và phương thức tĩnh:

Các đối tượng phương thức tĩnh Các đối tượng phương thức tĩnh cung cấp một cách để đánh bại sự chuyển đổi của các đối tượng hàm thành các đối tượng phương thức được mô tả ở trên. Một đối tượng phương thức tĩnh là một trình bao bọc xung quanh bất kỳ đối tượng nào khác, thường là đối tượng phương thức do người dùng định nghĩa. Khi một đối tượng phương thức tĩnh được lấy từ một lớp hoặc một thể hiện của lớp, đối tượng thực sự được trả về là đối tượng được bao bọc, không chịu sự biến đổi nào nữa. Các đối tượng phương thức tĩnh không phải là bản thân chúng có thể gọi được, mặc dù các đối tượng chúng bao bọc thường là. Các đối tượng phương thức tĩnh được tạo bởi hàm tạo staticmethod () tích hợp.

Các đối tượng phương thức lớp Một đối tượng phương thức lớp, giống như một đối tượng phương thức tĩnh, là một trình bao bọc xung quanh một đối tượng khác làm thay đổi cách thức mà đối tượng đó được truy xuất từ ​​các lớp và các thể hiện của lớp. Hành vi của các đối tượng phương thức lớp khi truy xuất như vậy được mô tả ở trên, bên dưới các phương thức do người dùng định nghĩa, ra. Các đối tượng phương thức lớp được tạo bởi hàm tạo classmethod () tích hợp.

Câu hỏi liên quan


4
@LightnessRacesinOrbit: Tôi không nghĩ các phương thức tĩnh được sử dụng đặc biệt thường xuyên trong python. Sử dụng hệ thống của tôi như một mẫu ngẫu nhiên, khi tôi tìm kiếm trong tất cả các gói tôi đã cài đặt, chỉ có khoảng 1% trong số tất cả các phương thức là phương thức tĩnh (mà thực sự là nhiều hơn tôi mong đợi).
Bryan Oakley

1
"Các phương thức tĩnh" thường là một mùi mã và không được khuyến khích bởi ví dụ như hướng dẫn kiểu Python của Python.
9000

3
Tôi nghĩ rằng câu trả lời sẽ tốt hơn nếu nó thu hút sự chú ý đến các lớp con, đó là nơi mà các lớp đối xứng nhận được một số hữu ích.
Winston Ewert

1
@ user2357112: Tôi chỉ đơn giản là đếm tất cả các trường hợp "^ def(", sau đó đếm tất cả các trường hợp của @staticmethod. Rất không khoa học, nhưng có lẽ là trong sân bóng.
Bryan Oakley

2
@Kashyap: TL; DR áp dụng cho đoạn đầu tiên. Tôi nghĩ rằng nó hoạt động tốt hơn ở phía trên so với phía dưới.
Bryan Oakley

8

Các phương thức lớp của Wikipedia là gì

  • Một "phương thức cá thể" sử dụng thông tin có trong thể hiện để tìm ra giá trị nào sẽ trả về (hoặc tác dụng phụ nào sẽ làm). Đây là rất phổ biến.

  • Một "phương thức lớp" sử dụng thông tin về lớp (và không phải là một thể hiện của lớp đó) để ảnh hưởng đến những gì nó làm (chúng thường được sử dụng để tạo các thể hiện mới như các hàm tạo thay thế, và do đó không phổ biến lắm).

  • Một "phương thức tĩnh" không sử dụng bất kỳ thông tin nào về lớp hoặc thể hiện để tính toán những gì nó làm. Nó thường chỉ trong lớp cho thuận tiện. (Như vậy, những điều này cũng không phổ biến lắm.)

Hàm của X

Hãy nhớ lớp toán, "y là hàm của x , f(x)?" Hãy áp dụng mã đó:

y = function(x)

Ngụ ý ở trên là vì xcó thể thay đổi, ycó thể thay đổi khi xthay đổi. Đây là những gì có nghĩa là khi chúng ta nói rằng " ylà một chức năng của x"

Điều gì sẽ yđược khi z1? 2? 'FooBarBaz'?

ykhông phải là một chức năng của z, vì vậy zcó thể là bất cứ điều gì và không ảnh hưởng đến kết quả của chức năng giả sử chúng ta functionlà một hàm thuần túy. (Nếu nó truy cập znhư một biến toàn cục, thì đó không phải là một hàm thuần túy - đây là ý nghĩa của độ tinh khiết chức năng.)

Hãy ghi nhớ những điều trên khi bạn đọc các mô tả sau:

Phương pháp sơ thẩm

Một phương thức thể hiện là chức năng là một chức năng của một thể hiện . Hàm chấp nhận thể hiện ngầm định làm đối số cho nó và thể hiện được hàm sử dụng để xác định đầu ra của hàm.

Một ví dụ tích hợp của một phương thức cá thể là str.lower:

>>> 'ABC'.lower()
'abc'

str.lower được gọi theo thể hiện của chuỗi và nó sử dụng thông tin có trong thể hiện để tìm ra chuỗi mới nào sẽ trả về.

Phương pháp lớp học:

Hãy nhớ rằng, trong Python, mọi thứ đều là một đối tượng. Điều đó có nghĩa là lớp là một đối tượng và có thể được truyền dưới dạng đối số cho hàm.

Một phương thức lớp là một hàm là một hàm của lớp . Nó chấp nhận lớp như là một đối số với nó.

Một ví dụ dựng sẵn là dict.fromkeys:

>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}

Hàm ngầm biết lớp riêng của nó, hàm sử dụng lớp để ảnh hưởng đến đầu ra của hàm và nó tạo ra một lớp mới của lớp đó từ iterable. Một OrderedDict chứng minh điều này khi sử dụng cùng một phương thức:

>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])

Phương thức lớp sử dụng thông tin về lớp (và không phải là một thể hiện của lớp đó) để ảnh hưởng đến loại lớp nào sẽ trả về.

Phương pháp tĩnh

Bạn đề cập đến một phương thức "không biết lớp của nó" - đây là một phương thức tĩnh trong Python. Nó chỉ được đính kèm để thuận tiện cho đối tượng lớp. Nó có thể tùy chọn là một chức năng riêng biệt trong một mô-đun khác, nhưng chữ ký cuộc gọi của nó sẽ giống nhau.

Một phương thức tĩnh là một hàm của cả lớp và đối tượng.

Một ví dụ tích hợp của một phương thức tĩnh là str.maketrans từ Python 3.

>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}

Đưa ra một vài đối số, nó tạo ra một từ điển không phải là một chức năng của lớp.

Nó thuận tiện vì strluôn có sẵn trong không gian tên toàn cầu, vì vậy bạn có thể dễ dàng sử dụng nó với chức năng dịch:

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'

Trong Python 2, bạn phải truy cập nó từ stringmô-đun:

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'

Thí dụ

class AClass(object):
    """In Python, a class may have several types of methods: 
    instance methods, class methods, and static methods
    """

    def an_instance_method(self, x, y, z=None):
        """this is a function of the instance of the object
        self is the object's instance
        """
        return self.a_class_method(x, y)

    @classmethod
    def a_class_method(cls, x, y, z=None):
        """this is a function of the class of the object
        cls is the object's class
        """
        return cls.a_static_method(x, y, z=z)

    @staticmethod
    def a_static_method(x, y, z=None):
        """this is neither a function of the instance or class to 
        which it is attached
        """
        return x, y, z

Hãy khởi tạo:

>>> instance = AClass()

Bây giờ cá thể có thể gọi tất cả các phương thức:

>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)

Nhưng lớp thường không có ý định gọi phương thức cá thể, mặc dù nó được dự kiến ​​sẽ gọi các phương thức khác:

>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'

Bạn sẽ phải thông qua cá thể để gọi phương thức cá thể:

>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)

"đây là một phương thức tĩnh trong Python. Nó chỉ được gắn để thuận tiện cho đối tượng lớp. Nó có thể tùy ý là một hàm riêng biệt trong một mô-đun khác, nhưng chữ ký cuộc gọi của nó sẽ giống nhau." Có vẻ khó hiểu hơn thuận tiện. Tại sao bạn lại gắn một hàm vào một lớp nếu cơ thể của nó sẽ không có khái niệm về lớp đó.
Cuộc đua nhẹ nhàng với Monica

@LightnessRacesinOrbit Tôi đã xây dựng từng điểm
Aaron Hall

Cá nhân, cách mà tôi luôn nhìn vào đó là một phương thức cá thể là một hoạt động trên một cá thể cụ thể, một phương thức lớp là một loại hàm tạo (để thuận tiện, không có gì giống như MyClass(1,2,3)thay vào đó, MyClass.get_special(1,2,3)) và một phương thức tĩnh như chỉ là là một chức năng bình thường có thể đứng một mình nào.
Zizouz212

Có, classmethod thường được sử dụng cho các hàm tạo thay thế (xem ví dụ dict.fromkeys của tôi ở trên, xem thêm mã nguồn pandas.DataFrame), nhưng đó không phải là một đặc điểm xác định. Đôi khi tôi chỉ cần truy cập dữ liệu được lưu trữ ở cấp lớp từ một phương thức mà không cần truy cập thể hiện. Nếu bạn đang gọi loại (tự) (hoặc tệ hơn, tự .__ class__) và không sử dụng trực tiếp bản thân trong một phương thức cá thể, đó là một dấu hiệu tốt cho thấy bạn nên coi đó là một phân loại. Vì classmethods không yêu cầu các thể hiện, điều đó làm cho chúng dễ dàng hơn trong việc hủy bỏ.
Aaron Hall

4
  • "Phương thức cá thể" là một phương thức được truyền đối tượng thể hiện làm tham số đầu tiên của nó, theo quy ước được gọi self. Đây là mặc định.

  • "Phương thức tĩnh" là phương thức không có selftham số ban đầu . Điều này được thực hiện với trang trí @staticmethod .

  • "Phương thức lớp" là một phương thức trong đó tham số ban đầu không phải là một đối tượng thể hiện, mà là đối tượng lớp ( xem phần tài liệu Python này để biết "đối tượng lớp" là gì), theo quy ước được gọi cls. Điều này được thực hiện với trình trang trí @ classmethod .

Cách sử dụng điển hình của thuật ngữ "phương thức tĩnh" trong C / C ++ / etc áp dụng cho cả hai phương thức "tĩnh" và "lớp" Python, vì cả hai loại phương thức này đều không tham chiếu đến thể hiện. Trong C / C ++ / etc, các phương thức thường có quyền truy cập ngầm vào tất cả các thành viên / phương thức không phải là cá thể của lớp, đó có thể là lý do tại sao sự khác biệt này chỉ tồn tại trong các ngôn ngữ như Python / Ruby / etc.


Phương thức tĩnh trong C / C ++ có tham chiếu đến đối tượng lớp không? Hay chỉ là "thành viên" của lớp? Họ có thể tạo thành viên mới của lớp không? :)
Aaron Hall

3
@AaronHall Trong C / C ++, không có đối tượng lớp nào và bạn không cần tham chiếu đến nó để gọi các phương thức tĩnh. Bạn chỉ cần viết Class::staticMethod()và đó là nó (miễn là bạn không bị cấm gọi nó vì nó staticMethod()là riêng tư hoặc một cái gì đó).
Ixrec
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.