独立的功能或方法

Tim*_*man 6 python api readability

我需要以一种方式处理类的两个对象,它将返回同一个类的第三个对象,并且我试图确定是否更好地将它作为一个独立的函数来接收两个对象并返回第三个或作为一种方法,它将采取另一个对象并返回第三个.


举个简单的例子.这会是:

from collections import namedtuple

class Point(namedtuple('Point', 'x y')):
    __slots__ = ()
    #Attached to class
    def midpoint(self, otherpoint):
        mx = (self.x + otherpoint.x) / 2.0
        my = (self.y + otherpoint.y) / 2.0
        return Point(mx, my)

a = Point(1.0, 2.0)
b = Point(2.0, 3.0)

print a.midpoint(b)
#Point(x=1.5, y=2.5)
Run Code Online (Sandbox Code Playgroud)

或这个:

from collections import namedtuple

class Point(namedtuple('Point', 'x y')):
    __slots__ = ()


#not attached to class
#takes two point objects
def midpoint(p1, p2):
    mx = (p1.x + p2.x) / 2.0
    my = (p1.y + p2.y) / 2.0
    return Point(mx, my)


a = Point(1.0, 2.0)
b = Point(2.0, 3.0)

print midpoint(a, b)
#Point(x=1.5, y=2.5)
Run Code Online (Sandbox Code Playgroud)

为什么一个人比另一个人更受欢迎?


当我提出问题时,这似乎远没有我预期的那么明确.

总之,似乎a.midpoint(b)之类的东西似乎不是优选的,因为它似乎在一个真正的对称函数返回一个全新的点实例的某一点给出了一个特殊的位置.但它似乎主要是在类似独立模块函数或附加到类的函数之间的味道和风格问题,但并不意味着被insance调用,例如Point.midpoint(a,b).

我个人认为,我在风格上倾向于独立的模块功能,但这可能取决于具体情况.如果函数肯定与类紧密绑定,并且存在命名空间污染或潜在混淆的风险,那么创建类函数可能更有意义.

此外,有几个人提到使函数更通用,可能通过实现类的其他功能来支持它.在处理点和中点的这种特殊情况下,这可能是整体最佳方法.它支持多态和代码重用,并且具有高可读性.但在很多情况下,这样做是行不通的(这个项目激励我去问这个例子),但是点和中点似乎是一个简洁易懂的例子来说明这个问题.

谢谢大家,这很有启发性.

Nat*_*han 2

我会选择第二个选项,因为在我看来,它比第一个更清晰。您正在执行两点之间的中点运算;不是针对某个点的中点运算。类似地,该接口的自然扩展可以是定义dotcrossmagnitudeaveragemedian等。其中一些函数将在成对上运行Points,而其他函数可能在列表上运行。使其成为一个函数使得它们都具有一致的接口。

将其定义为函数还允许它与任何呈现接口的对象对一起使用.x .y,而将其定义为方法则要求两者中至少有一个是Point.

最后,为了解决函数的位置问题,我认为将其与 Point 类放在同一个包中是有意义的。这将它放在同一个命名空间中,这清楚地表明了它与静态或类方法的关系Point,并且在我看来,它比静态或类方法更具Python风格。

更新: 进一步阅读 vs 包/模块的 Pythonicness @staticmethod

在 Thomas Wouter 对What is the Difference between staticmethod and classmethod in Python问题的回答以及 Mike Steder 对Python 中init和 argument 的回答中,作者指出相关函数的包或模块可能是更好的解决方案。托马斯·沃特有这样的说法:

[staticmethod] 在 Python 中基本上没有用——你可以只使用模块函数而不是 staticmethod。

迈克·斯特德 (Mike Steder) 评论道:

如果您发现自己创建的对象只包含静态方法,那么更 Pythonic 的做法是创建一个相关函数的新模块。

然而,codeape 在下面正确地指出, 的调用约定Point.midpoint(a,b)会将功能与类型放在一起。BDFL 似乎也很有价值,@staticmethod因为该__new__方法是staticmethod.

出于上述原因,我个人倾向于使用函数,但似乎在@staticmethod独立函数之间进行选择很大程度上取决于旁观者的看法。