首页 > 解决方案 > 成员上的python类操作与静态方法

问题描述

我需要一些帮助来确定我的 python 类的正确 OOP 设计选择。

在我的示例中,字母在单独的步骤中附加到字符串。然后打印字符串。对于这个应用程序,获得中间结果对用户来说并不重要。

那么将字符串传递给构造函数然后使用私有方法进行操作和dothings调用它们的方法更好吗?

class A:
    def __init__(self, string: str()):
        self.string = string

    def _append_a(self):
        self.string += "a"

    def _append_b(self):
        self.string += "b"

    def dothings(self):
        _append_a()
        _append_b()

    def export(self):
        print(self.string)

还是将字符串传递给每个方法更好?

class AA:
    @staticmethod
    def append_a(string):
        string += "a"
        return string

    @staticmethod
    def append_b(string):
        string += "b"
        return string

    @staticmethod
    def export(string):
        print(string)

界面A对我来说看起来有点干净,一个可以调用dothings然后导出。然而,类A有点像一个黑盒子,而有了类AA,用户对正在发生的事情有了更多的了解。

对此有“正确”的选择吗?

标签: pythonoopsoftware-designdesign-principles

解决方案


AA很容易被解雇。它没有任何面向对象的东西:它只是将三个常规函数收集到一个命名空间中。没有由一组方法操作的共享状态。没有建议只有一个函数的输出是另一个函数的有效输入。例如,意图可能是写类似

export(append_a(append_b("foo")))  # fooba

但没有什么要求遵循这种模式。无论如何,这些功能彼此无关。

A与建造者模式有一些共同点。给定一个初始字符串,您可以将as 和bs 附加到它上面,但仅此而已(不违反方法提供的封装。最终,您通过调用 获得“最终”值export,因此它所代表的工作流程类似于:

a = A("foo")
a.append_a()
a.append_a()
a.append_b()
a.append_b()
a.append_a()
a.export()  # fooaabba

所示的类几乎非常简单,但演示了如何提供定义良好的接口来从初始种子构建字符串值。你不能只是用它做任何你喜欢的事情:你不能在前面加上值,你不能删除现有的字符,等等。


为了更符合构建器模式,我将修改A如下:

class A:
    def __init__(self, string: str):
        self.string = string

    def append_a(self):
        self.string += "a"

    def append_b(self):
        self.string += "b"

    def append_ab(self):
        self.append_a()
        self.append_b()

    def export(self):
        return self.string + "c"  

只要您不string直接访问该属性,此类就会限制您可以构建的字符串类型:

  1. 您可以从任意词干开始( 的参数__init__
  2. 您可以将一个附加a到字符串
  3. 您可以将 a 附加b到字符串
  4. 您可以将 an 附加ab到字符串(但这只是调用append_a后跟的便捷快捷方式append_b,正如实现所暗示的那样)
  5. 您可以使用结束字符串c

你通过调用得到你的最终值export(我修改它只是为了说明你不能c在任何时候添加 a ,所以没有办法跟随 ac与 another a,例如)。

从某种意义上说,它是正则表达式的对偶:不是识别字符串是否与正则表达式匹配.*(a|b)*c,而是创建一个与正表达式匹配的字符串。


推荐阅读