Cách tốt để sắp xếp các phương thức trong một lớp Python là gì?


86

Tôi muốn sắp xếp thứ tự các phương thức trong một lớp Python nhưng tôi không biết đâu là thứ tự chính xác.

Khi tôi trích xuất các phương thức trong Eclipse bằng PyDev, Eclipse đặt phương thức được trích xuất lên trên phương thức đã sửa đổi. Nhưng điều này đặt các chi tiết cấp thấp hơn trước các chi tiết cấp cao hơn. Theo chú Bob, tôi nên làm ngược lại để mã của tôi đọc giống như tiêu đề của một tờ báo. Khi tôi lập trình Java, tôi chỉ làm theo lời khuyên của anh ấy.

Thực hành tốt nhất cho Python là gì?


8
Không có một phương pháp hay nhất. Làm những gì có ý nghĩa nhất - những thứ quan trọng ở gần đầu là một ý tưởng hay và tính nhất quán nói chung là một điều tốt. PEP-8 không đề cập đến điều này, và nếu nó được đặt trong đá, đó là nơi nó sẽ ở.
Gareth Latty

4
Và thậm chí PEP8 không phải lúc nào cũng được đặt trong tình trạng khó khăn.
Ignacio Vazquez-Abrams

1
Tôi thường làm điều đó bởi nhóm trên các chức năng (nhận được, thiết lập, vv)
CppLearner

Điều quan trọng cần lưu ý là thứ tự của các hàm phương thức có thể là tùy ý, vì khai báo lớp chỉ định nghĩa các hàm phương thức của nó chứ không gọi chúng. Điều này cho phép mã nguồn của quy trình phương thức lớp sử dụng thành công các hàm phương thức sẽ được định nghĩa sau này trong danh sách.
DragonLord ngày

Câu trả lời:


64

Như những người khác đã chỉ ra, không có cách nào đúng để sắp xếp các phương pháp của bạn. Có thể một gợi ý PEP sẽ hữu ích, nhưng dù sao. Hãy để tôi cố gắng tiếp cận câu hỏi của bạn một cách khách quan nhất có thể.

  • Giao diện đầu tiên: Các phương thức công khai và hàm ma thuật Python xác định giao diện của lớp. Hầu hết thời gian, bạn và các nhà phát triển khác muốn sử dụng một lớp hơn là thay đổi nó. Như vậy họ sẽ quan tâm đến giao diện của lớp đó. Đặt nó đầu tiên trong mã nguồn tránh việc cuộn qua các chi tiết triển khai mà bạn không quan tâm.

  • Thuộc tính, phương thức ma thuật , phương thức công khai: Thật khó để xác định thứ tự tốt nhất giữa ba thứ đó, tất cả đều là một phần của giao diện của lớp. Như @EthanFurman nói, điều quan trọng nhất là gắn bó với một hệ thống cho toàn bộ dự án. Nói chung, mọi người mong đợi __init__()hàm đầu tiên tốt nhất trong lớp, vì vậy tôi theo dõi các phương pháp ảo thuật khác ngay bên dưới.

  • Thứ tự đọc: Về cơ bản, có hai cách để kể một câu chuyện: Từ dưới lên hoặc từ trên xuống. Bằng cách đặt các chức năng cấp cao lên hàng đầu, một nhà phát triển có thể hiểu sơ bộ về lớp bằng cách đọc vài dòng đầu tiên. Nếu không, người ta sẽ phải đọc toàn bộ lớp học để có được bất kỳ sự hiểu biết nào về lớp học và hầu hết các nhà phát triển không có thời gian cho việc đó. Theo quy tắc chung, hãy đặt các phương thức lên trên tất cả các phương pháp được gọi từ cơ thể của chúng.

  • Phương thức lớp và phương thức tĩnh: Thông thường, điều này được ngụ ý bởi thứ tự đọc được giải thích ở trên. Các phương thức thông thường có thể gọi tất cả các phương thức lần và do đó đến trước. Phương thức lớp chỉ có thể gọi phương thức lớp và phương thức tĩnh và đến tiếp theo. Các phương thức static không thể gọi các phương thức khác của lớp và đến sau cùng.

Hi vọng điêu nay co ich. Hầu hết các quy tắc này không dành riêng cho Python. Tôi không biết về một ngôn ngữ thực thi thứ tự phương thức nhưng nếu vậy, nó sẽ khá thú vị và vui lòng bình luận.


1
Thông thường một ngôn ngữ không thực thi thứ tự. Nhưng một số ngôn ngữ có những quy ước chung. Ví dụ: C # StyleCop có quy tắc đặt hàng nghiêm ngặt. Đối với Java, hãy xem stackoverflow.com/questions/4668218 , v.v.
xmedeko

1
các phương thức lớp: chúng thường được sử dụng làm hàm tạo và sau đó chúng thường gọi __init__một cách rõ ràng (kết hợp với __new__) hoặc ngầm định (thông qua hàm tạo mặc định), vì vậy đó sẽ là lý do để đặt chúng cùng với __init__. (Mặc dù tôi chưa bao giờ thấy họ đặt trước __init__ .)
oulenz

13

Không có một thứ tự chính xác. Chọn một hệ thống và gắn bó với nó. Một trong những tôi sử dụng là:

class SomeClass(object):
    def __magic_methods__(self):
        "magic methods first, usually in alphabetical order"
    def _private_method(self):
        "worker methods next, also in alpha order"
    def a_method(self):
        "then normal methods, also in alpha order"

2
Sở thích của bạn đối với staticmethods, biến lớp và phương thức được trang trí @property là gì?
John Mee

@JohnMee: biến lớp tôi đặt trước bất kỳ thứ gì khác; gấp phương pháp da của tôi @staticmethod, @classmethod, @property, và bất kỳ khác @decoratordòng nên tôi sử dụng loại phương pháp này để xác định nơi nó đi (ngoại trừ rằng tài sản có xu hướng đi giữa _private_methodsnormal_methods).
Ethan Furman

Vì vậy, nếu thứ tự về cơ bản đi từ các phương thức "ma thuật" rất riêng tư đến các phương thức bình thường, điều đó có nghĩa là @classmethods đến sau ( @classmethod def a_class_method(cls)) rồi @staticmethods ( @staticmethod def a_static_method())? Ít nhất đó là chính sách như tôi hiểu nó ... (không có IDE của tôi gấp bất cứ điều gì bởi vì tôi không như thế)
Kawu

2

Tôi làm điều gì đó tương tự như @Ethan mà tôi đã thấy trong nguồn của Django, trong đó sự khác biệt chính là "#############" chặn nhận xét để phân định các khu vực. Ví dụ,

class SomeClass(object):
    #################
    # Magic Methods #
    #################
    def __magic_methods__(self):
        "magic methods first"

    ##################
    # Public Methods #
    ##################
    def a_method(self):
        "then normal methods, in order of importance"

    ###################
    # Private Methods #
    ###################
    def _private_method(self):
        "then worker methods, grouped by importance or related function"

Rõ ràng là điều này ít hữu ích hơn cho các lớp nhỏ hơn.


19
Nhưng tôi có thể thấy rằng chúng là ma thuật, công khai hay riêng tư. Tôi chủ động không thích những khối bình luận như vậy, bản thân tôi; Tôi có thể xem mã được gấp lại nếu tôi muốn xem danh sách tất cả chúng. Có một nhận xét phía trên một khối cụ thể của các phương thức liên quan đến chức năng là điều tôi muốn làm, nhưng đối với loại nhận xét này - đó là những gì tên phương thức cho tôi biết.
Chris Morgan

Một lần nữa, tôi chỉ làm điều này cho các lớp lớn hơn. Tôi thấy rất dễ nhầm lẫn giữa các phương thức ma thuật với các phương thức semi-private ( ) và name-mangled (_ ).
Matt Luongo

Tôi đang trong quá trình chỉnh sửa để loại bỏ các ####khối xấu xí thì tôi nhận ra rằng bạn đã cố ý đặt chúng ở đó ! Tuy nhiên, tôi đồng ý với đơn đặt hàng , đó là những gì câu hỏi này là về. Tôi khuyên bạn nên xóa tên ####khỏi ví dụ này vì nó không liên quan đến phạm vi của câu hỏi và ví dụ của bạn thuộc một lớp nhỏ, mà bạn sẽ không sử dụng bất kỳ loại nào ####. :-)
Mateen Ulhaq

1
@MateenUlhaq vui lòng tham khảo hướng dẫn thứ hai và thứ năm hiển thị trên màn hình chỉnh sửa: "làm rõ nghĩa mà không thay đổi nó" và " luôn tôn trọng tác giả gốc". (Lưu ý rằng chúng được áp dụng vô điều kiện, không theo ý kiến ​​riêng của người biên tập.) Điểm toàn bộ và duy nhất của câu trả lời này là hiển thị những khối bình luận xấu xí đó; nếu không có họ, nó nói điều tương tự như câu trả lời của Ethan và không có ý nghĩa gì cho nó ở đây. Bạn thậm chí đã thừa nhận rằng các khối đã ở đó "có chủ đích " - biết điều này, tại sao bạn sẽ đi và xóa chúng?
hallo

1
@MIWright Tôi nghĩ nó nằm ngoài phạm vi của câu hỏi. Như bạn có thể thấy, rev2 vẫn chứa tài liệu trả lời câu hỏi khác với của Ethan, với một thứ tự khác (và sắp xếp con!). Tuy nhiên, đã quay trở lại.
Mateen Ulhaq,
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.