Jaki jest dobry sposób zamawiania metod w klasie Pythona?

86

Chcę zamówić metody w klasie Pythona, ale nie wiem, jaka jest właściwa kolejność.

Kiedy wyodrębniam metody w Eclipse za pomocą PyDev, Eclipse umieszcza wyodrębnioną metodę na wierzchu zmodyfikowanej metody. Ale to stawia szczegóły niższego poziomu przed szczegółami wyższego poziomu. Według wujka Boba powinienem zrobić coś odwrotnego, żeby mój kod brzmiał jak nagłówki gazety. Kiedy programuję Javę, po prostu postępuję zgodnie z jego radą.

Jaka jest najlepsza praktyka w Pythonie?

zetafish
źródło
8
Nie ma najlepszej praktyki. Rób to, co jest najbardziej sensowne - ważne rzeczy blisko szczytu to dobry pomysł, a spójność jest ogólnie dobra. PEP-8 o tym nie wspomina, a gdyby miał być osadzony w kamieniu, to właśnie tam by się znajdował.
Gareth Latty
4
A nawet PEP8 nie zawsze jest osadzony w kamieniu.
Ignacio Vazquez-Abrams
1
I zazwyczaj to zrobić przez grupy na funkcjonalność (Get Set, itp)
CppLearner
Należy zauważyć, że kolejność funkcji metod może być dowolna, ponieważ deklaracja klasy definiuje tylko jej funkcje metod, a nie je wywołuje . Dzięki temu kod źródłowy procedur klasowych może z powodzeniem używać funkcji metod, które zostaną zdefiniowane później na liście.
DragonLord

Odpowiedzi:

64

Jak zauważyli inni, nie ma właściwego sposobu na zamówienie swoich metod. Może sugestia PEP byłaby przydatna, ale tak czy inaczej. Spróbuję podejść do twojego pytania tak obiektywnie, jak to tylko możliwe.

  • Najpierw interfejsy: metody publiczne i magiczne funkcje Pythona definiują interfejs klasy. W większości przypadków Ty i inni programiści chcecie używać klasy, zamiast ją zmieniać. Dlatego będą zainteresowani interfejsem tej klasy. Umieszczenie go na pierwszym miejscu w kodzie źródłowym pozwala uniknąć przewijania szczegółów implementacji, które Cię nie interesują.

  • Właściwości, metody magiczne, metody publiczne: Trudno jest zdefiniować najlepszą kolejność między tymi trzema, które są częścią interfejsu klasy. Jak mówi @EthanFurman, najważniejsze jest, aby trzymać się jednego systemu dla całego projektu. Ogólnie rzecz biorąc, ludzie oczekują __init__()najlepszej pierwszej funkcji w klasie, więc poniżej przedstawiam inne magiczne metody.

  • Kolejność czytania: Zasadniczo istnieją dwa sposoby opowiadania historii: oddolne lub odgórne. Umieszczając na pierwszym miejscu funkcje wysokopoziomowe, programista może z grubsza zrozumieć klasę, czytając kilka pierwszych wierszy. W przeciwnym razie należałoby przeczytać całą klasę, aby uzyskać jakiekolwiek zrozumienie klasy, a większość programistów nie ma na to czasu. Z zasady stawiaj metody ponad wszystkie metody wywoływane z ich ciała.

  • Metody klasowe i metody statyczne: Zwykle wynika to z kolejności czytania wyjaśnionej powyżej. Normalne metody mogą wywoływać wszystkie metody razy i dlatego są pierwsze. Metody klasowe mogą wywoływać tylko metody klasowe i metody statyczne i są następne. Metody statyczne nie mogą wywoływać innych metod tej klasy i zajmować ostatniego miejsca.

Mam nadzieję że to pomoże. Większość z tych reguł nie jest specyficzna dla Pythona. Nie znam języka, który wymusza kolejność metod, ale jeśli tak, byłoby to dość interesujące i proszę o komentarz.

danijar
źródło
1
Zazwyczaj język nie wymusza nakazu. Ale niektóre języki mają wspólne konwencje. Np. C # StyleCop ma ścisłe zasady porządkowania. W przypadku języka Java patrz stackoverflow.com/questions/4668218 itp.
xmedeko
1
metody klas: są one często używane jako konstruktory, a następnie wywołują je __init__jawnie (w połączeniu z __new__) lub niejawnie (za pośrednictwem domyślnego konstruktora), więc byłby to powód do umieszczenia ich razem z __init__. (Chociaż nigdy nie widziałem ich umieszczony przed __init__ .)
oulenz
13

Nie ma jednej prawidłowej kolejności. Wybierz system i trzymaj się go. Ten, którego używam, to:

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"
Ethan Furman
źródło
2
Jakie są Twoje preferencje dotyczące metod statycznych, zmiennych klas i metod dekorowanych @property?
John Mee,
@JohnMee: zmienne klas, które stawiam przed wszystkim innym; Moja metoda składane ukrywa @staticmethod, @classmethod, @propertyoraz wszelkie inne @decoratorlinie więc używam rodzaj metody, aby określić, gdzie to idzie (z wyjątkiem tego, że właściwości mają tendencję, aby przejść między _private_methodsa normal_methods).
Ethan Furman,
Więc jeśli kolejność zasadniczo przechodzi od bardzo prywatnych metod „magicznych” do metod prywatnych do normalnych, czy to oznacza, że @classmethods come next ( @classmethod def a_class_method(cls)), a następnie @staticmethods ( @staticmethod def a_static_method())? Przynajmniej taka jest polityka, jaką rozumiem ... (bez mojego IDE składającego cokolwiek, ponieważ mi się to nie podoba)
Kawu
2

Robię coś podobnego do @Ethan, które widziałem w kodzie źródłowym Django, gdzie główna różnica jest duża "############" blok komentarzy, aby rozgraniczać obszary. Na przykład,

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"

Oczywiście jest to mniej przydatne dla mniejszych klas.

Matt Luongo
źródło
19
Ale widzę, że są magiczne, publiczne lub prywatne. Sam aktywnie nie lubię takich bloków komentarzy; Mogę spojrzeć na zwinięty kod, jeśli chcę zobaczyć ich listę. Umieszczenie komentarza nad konkretnym blokiem metod powiązanych z funkcjonalnością jest czymś, co zrobiłbym, ale w przypadku tego typu komentarza - to właśnie mówią mi nazwy metod.
Chris Morgan,
Znowu robię to tylko dla większych klas. Uważam, że łatwo jest pomylić metody magiczne z metodami półprywatnymi ( ) i zniekształconymi (_ ).
Matt Luongo
Byłem w połowie edycji usuwając brzydkie ####bloki, kiedy zdałem sobie sprawę, że umieściłeś je tam celowo! Zgadzam się jednak z zamówieniem , o co chodzi w tym pytaniu. Zalecałbym usunięcie ####z tego przykładu, ponieważ nie dotyczy to zakresu pytania, a Twój przykład należy do małej klasy, której i tak byś nie używał ####. :-)
Mateen Ulhaq
1
@MateenUlhaq zapoznaj się z drugą i piątą wskazówką wyświetlaną na ekranie edycji: „wyjaśnij znaczenie bez zmiany” i „ zawsze szanuj oryginalnego autora”. (Zauważ, że mają one być stosowane bezwarunkowo, bez względu na własną opinię redaktora). Całość i jedyny punkt tej odpowiedzi polegała na wyświetleniu tych brzydkich bloków komentarzy; bez nich mówi dokładnie to samo, co odpowiedź Ethana i nie ma sensu, aby tu było. Przyznałeś nawet, że bloki były tam „ celowo ” - wiedząc o tym, dlaczego miałbyś je usuwać?
witaj,
1
@MIWright Myślałem, że to wykracza poza zakres pytania. Jak widać, rev2 nadal zawiera materiał, który odpowiada na pytanie inaczej niż Ethan, z inną kolejnością (i podporządkowaniem!). Niemniej jednak wycofany.
Mateen Ulhaq