在Python类中排序方法的好方法是什么?


86

我想在Python类中对方法进行排序,但是我不知道正确的顺序是什么。

当我使用PyDev在Eclipse中提取方法时,Eclipse会将提取的方法放在修改后的方法之上。但这会将较低级别的详细信息放在较高级别的详细信息之前。根据鲍伯叔叔的说法,我应该做相反的事情,以便我的代码读起来像报纸的头条新闻。当我编写Java程序时,我只是遵循他的建议。

Python的最佳做法是什么?


8
没有最佳实践。做最有意义的事情-靠近顶部的重要内容是个好主意,而一致性通常是一件好事。PEP-8没有提及这一点,如果要固定在石头上,那就是它的原位。
Gareth Latty

4
甚至PEP8也不总是一成不变的。
伊格纳西奥·巴斯克斯

1
我通常按​​功能(获取,设置等)
分组进行操作

重要的是要注意,方法函数的顺序可以是任意的,因为类声明仅定义其方法函数,而不是调用它们。这使类方法例程的源代码能够成功使用方法功能,这些功能将在清单的后面部分进行定义。
6

Answers:


64

正如其他人指出的那样,没有正确的方法来订购您的方法。PEP建议可能会有用,但是无论如何。让我尝试尽可能客观地解决您的问题。

  • 首先接口:公共方法和Python魔术函数定义类的接口。大多数时候,您和其他开发人员都想使用一个类而不是更改它。因此,他们将对该类的接口感兴趣。将其放在源代码中的第一位可避免滚动浏览您不需要的实现细节。

  • 属性,魔术方法,公共方法:很难定义这三个类之间的最佳顺序,它们都是类接口的一部分。正如@EthanFurman所说,在整个项目中坚持使用一个系统是最重要的。通常,人们期望__init__()在班级中拥有最好的第一功能,因此我将介绍下面的其他魔术方法。

  • 阅读顺序:基本上,有两种讲故事的方法:自下而上或自上而下。通过将高级功能放在首位,开发人员可以通过阅读前几行来大致了解该类。否则,人们将不得不阅读整个课程,以对课程有所了解,而大多数开发人员却没有时间这样做。根据经验,将方法置于从其主体调用的所有方法之上。

  • 类方法和静态方法:通常,这由上面解释的阅读顺序暗含。普通方法可以调用所有方法,因此优先。类方法只能调用类方法和静态方法,然后继续。静态方法不能调用该类的其他方法并排在最后。

希望这可以帮助。顺便说一下,这些规则大多数都不是特定于Python的。我不知道强制执行方法顺序的语言,但是如果是这样,这将非常有趣,请发表评论。


1
通常,一种语言不强制执行排序。但是某些语言有共同的约定。例如,C#StyleCop具有严格的订购规则。对于Java,请参见stackoverflow.com/questions/4668218
-xmedeko

1
类方法:这些方法通常用作构造函数,然后通常会__init__显式调用(与组合__new__)或隐式调用(通过默认的构造函数),因此这就是将它们与放置在一起的原因__init__。(尽管我从未见过它们放置在前面 __init__。)
oulenz

13

没有正确的订单。选择一个系统并坚持下去。我使用的是:

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
您对静态方法,类变量和@property装饰方法有何偏好?
约翰·米

@JohnMee:我放在其他任何东西之前的类变量;我的折叠方法的生皮@staticmethod@classmethod@property,以及任何其他@decorator线,所以我使用的方法的种类,以确定它进入(不同之处在于性能倾向于之间去_private_methodsnormal_methods)。
伊桑·弗曼

因此,如果顺序基本上是从非常私有的“魔术”方法变为私有方法到普通方法,这是否意味着@classmethods@classmethod def a_class_method(cls)依次出现()和@staticmethods(@staticmethod def a_static_method())?至少这是我所了解的政策…… (我的IDE不会折叠任何东西,因为我不喜欢它)
Kawu 2014年

2

我做的事情类似于Django来源中看到的@Ethan,主要区别是大的“ ############”块注释来界定区域。例如,

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"

显然,这对于较小的类没有太大用处。


19
但是我可以看到它们是魔术的,公共的或私人的。我自己不喜欢这样的评论。如果要查看所有代码的清单,可以看一下折叠的代码。我会在特定于功能相关方法的特定块上方添加注释,但是对于这种类型的注释,这就是方法名称告诉我的。
克里斯·摩根

同样,我只对较大的班级这样做。我发现很容易将魔术方法与半私有()和名称混杂(_)方法混淆。
Matt Luongo 2012年

####当我意识到您会故意将丑陋的方块放到那里时,我正在编辑这些丑陋的方块我确实同意该命令,但这就是这个问题的意思。我建议####从此示例中删除,因为它与问题范围无关,并且您的示例属于小类,####无论如何您都不会使用。:-)
Mateen Ulhaq '18年

1
@MateenUlhaq请参阅编辑屏幕上显示的第二和第五条准则:“澄清含义而不更改它”和“始终尊重原始作者”。(请注意,这些是无条件地应用的,不考虑编辑者的个人意见。)此答案的全部且唯一的目的是显示那些丑陋的注释框;没有他们,它说的和Ethan的回答完全一样,就没有意义了。您甚至确实承认这些块是“故意”存在的-知道这一点,您为什么要删除它们?
hallo

1
@MIWright我认为它不在问题范围内。如您所见,rev2仍然包含与Ethan回答不同的材料,其排序方式(和子排序方式)不同。尽管如此,还是回滚了。
Mateen Ulhaq
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.