【问题标题】:Returning an object vs returning a tuple [closed]返回一个对象与返回一个元组[关闭]
【发布时间】:2010-10-22 02:28:01
【问题描述】:

我正在用 python 开发一个可以读写文件的文件类,其中包含 xyz 坐标列表。在我的程序中,我已经有一个 Coord3D 类来保存 xyz 坐标。

我的问题与 getCoordinate(index) 方法的设计有关。我应该返回一个浮点元组还是一个 Coord3D 对象?

在第一种情况下,我得到非常低的耦合,但是我可能不得不用获得的值实例化一个 Coord3D 对象,尽管在文件类之外。在第二种情况下,我将文件类与 Coord3D 类紧密耦合。

请注意,我认为这两种解决方案没有太大区别,但我想阅读您的答案及其背后的原因。


编辑:回顾一下我到目前为止得到的答案,看起来没有明确的选择。有人说(恰当地)python不是Java,你不需要一个专门的类来处理所有的事情,因为你需要它的语言架构。然而,就我而言,我有以下条件:

  1. 我正在开发一个库,其中 Coord3D 对象按原样使用。使用它会增加我的库的凝聚力,因为数据类型将被统一使用。
  2. Coord3D 对象具有状态和行为。实际上,Coord3D 对象将坐标和单位聚合在一个实体中。 Coord3D 对象之间的操作将考虑到潜在的不同单元,并采取相应的行动。
  3. 我可以将集中控制代码放入 Coord3D 类实例化中以拒绝,例如长度为 4 的数组或非单位的数组。如果我使用元组,则无法执行此检查。此外,如果一个方法接受 Coord3D,则可以保证它预先形成良好的格式(您可以大胆并检查 isinstance,或检查接口)。元组可以包含无效数据。尽管在出现问题的地方使用 python 方法进行错误处理,但阻止我使用由三个字符串组成的 xyz 坐标的类在某种程度上是有益的(如果有错误,请纠正我)

另一方面,使用元组有以下优点:

  1. 对资源的占用少,在巨大的情况下相当关键
  2. 更简单的设计。更多的类意味着更复杂的设计。元组是一种标准数据类型,易于理解并且可以轻松解包。个性化课程不是。
  3. 使用元组,XYZFile 类与库的其余部分完全分离(因为它不使用 Coord3D 对象)。这意味着它可以作为一个独立的实体完全重复使用。

欢迎更多的cmets!

【问题讨论】:

    标签: python


    【解决方案1】:

    折衷解决方案:将 Coord3D 改为 namedtuple 并返回 :-)

    用法:

    Coord3D = namedtuple('Coord3D', 'x y z')
    
    def getCoordinate(index):
        # do stuff, creating variables x, y, z
        return Coord3D(x, y, z)
    

    返回值可以完全用作元组,并且具有相同的速度和内存属性,因此不会失去任何通用性。但您也可以通过名称访问其值:如果 cgetCoordinate(index) 的结果,那么您可以使用 c.xc.y 等,以提高可读性。

    (如果您的 Coord3D 类也需要其他功能,这显然不太有用)

    [如果你不在python2.6上,你可以从cookbook recipe获取namedtuples]

    【讨论】:

    • 导入集合以在最新的 Python 上也有 namedtuple!
    【解决方案2】:

    如果其他人(除了你自己)将使用这个类,在我看来,返回一个对象会鼓励数据类型的某种一致性。如果 Coord3D 类有一个方法或属性可以将这些坐标作为一个元组访问,那么如果他们需要,这仍然会为他们提供该选项:

    # get the object
    coord_obj = my_obj.getCoordinate(my_index)
    # get the tuple (for example, via a property named "coords")
    coord_tup = my_obj.getCoordinate(my_index).coords
    

    【讨论】:

      【解决方案3】:

      更基本的问题是“你为什么有 Coord3D 类?”为什么不只使用元组?

      我们大多数人对 Python n00bz 的一般建议是“在必要之前不要发明新类。”

      您的 Coord3D 是否有独特的方法?也许你需要一门新课。或者——也许——你只需要一些对元组进行操作的函数。

      你的 Coord3D 有可变状态吗?几乎不可能。不可变元组开始看起来比新类更好。

      【讨论】:

      • 总的来说,我同意你的看法。然而,事情实际上更复杂。 Coord3D 在我的代码中无处不在,也是因为它与 Unum Unit 相关联。
      • 我认为 Python 的一句格言是“命名空间是一个伟大的想法——让我们做更多的事情!”。在这方面,一个类不是比一组相关函数(元组操作)更好吗?为什么你有一个类的状态要求?顺便说一句,我是 Python 新手,但我认为创建类的想法是一件好事——不是要避免的事情。
      • +1:添加类会增加复杂性,因此请避免使用它,除非有真正的好处(在这种情况下我看不到)。
      • 模块是一种“命名空间”;这有时比一堂课更好。通常在 OO 中,一个类封装了状态和行为。如果没有状态变化,那么......你没有太多的课程。在 Python 中,您不必像在 Java 中那样为每一件小事都创建类。特别是对于每一个不可变的小东西。
      【解决方案4】:

      看看 Will McGugan 的 Gameobjects library。他有一个Vector3 class,可以用另一个 Vector3 对象、一个元组、单个浮点值等进行初始化。我想这会回答你的问题......另外你可能最终只使用他的库,因为它已经优化并且有很多已经有很多有用的方法了。

      【讨论】:

      • 这个类绝对值得一看...通过查看它的(相当广泛但非常完整的)源代码,我学到了很多聪明的 Python 类和方法创建习惯用法。
      【解决方案5】:

      我也问过自己同样的问题,虽然是在做 2D 几何的时候。

      我为自己找到的答案是,如果我打算编写一个更大的库,具有更多功能等等,请继续返回 Point,或者在你的情况下返回 Coord3D 对象。如果它只是一个 hacky 实现,那么元组会让你走得更快。最后,这只是您将要使用它来做的事情,是否值得付出努力。

      【讨论】:

        【解决方案6】:

        如果它只在您的应用程序中使用,并且无论如何您要使用这些值创建一个Coord3D 实例,我只会返回一个Coord3D 实例以节省您的工作量。但是,如果您有兴趣使这个可移植/通用,请返回一个元组。无论如何,创建Coord3D 会很容易,使用

        c3d = Coord3D(*getCoordinate(index))
        

        (假设你的构造函数是Coord3D.__init__(self, x, y, z)

        【讨论】:

        • 不确定我喜欢这个。似乎暴露了一些无用的细节。我认为最好选择一种表示并坚持下去。
        【解决方案7】:

        返回一个对象将是最佳实践,并且会为您提供更好的整体软件设计。我建议这样做

        但请记住,创建/返回对象将花费更多处理时间。如果您经常执行此操作,它可能会改变一些东西,在这种情况下,您可能需要考虑一下......

        【讨论】:

          猜你喜欢
          • 2014-10-15
          • 1970-01-01
          • 2015-01-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-15
          • 2015-03-26
          • 2015-06-06
          相关资源
          最近更新 更多