【问题标题】:Working on a class shared between main program and a function处理在主程序和函数之间共享的类
【发布时间】:2017-06-12 09:06:30
【问题描述】:

如果我的问题看起来微不足道,我们深表歉意。我在缺席 15 年后才回到 OOP,我正在从 Java 迁移到 python。我已经广泛搜索了一个明确的答案,但没有找到。如果答案已经存在,请重定向我。

我正在寻找关于我所说的全局与本地类处理的最佳实践建议。我正在开发的实际应用程序的主程序似乎需要大约 4 个主要类(例如附加模型中的 Register 类),而构建系统网络的原理类将只有一个实例。每个主要类都将具有各种属性,包括嵌套类,例如 Person,并且这些嵌套类只会被用作这样的类,即永远不会被调用用作独立实例。

在示例中,我调用 newReg(我的“主”类)作为 Register 的实例。 '使用选项 1' 序列,我调用了 2 个函数来输入和输出动态数组 people 的内容。我没有将 newReg 作为参数传递给函数,因为它是我计划实例化的唯一 Register 类。实际上,我使用这些函数作为 GOSUB...RETURN 例程(如果你们中的任何人曾经使用过 BASIC)试图整理主程序(到目前为止,我的实际应用程序中的草稿方法有许多循环和检查以及嵌套菜单调用我想将这些作为块与主程序逻辑流分开)。但是,这似乎不是很 OOP,但由于我只需要在主程序中将函数作为 GOSUB...RETURN,这似乎是一种务实的方法。但这是一种好的做法吗?

替代选项 2 序列确实将 newReg 作为参数传递给函数,并且通过适当修改的函数,我得到相同的结果。这看起来确实更 OOP,但如果只有一个名为 newReg 的 Register 实例,我看不到这样做的好处。事实上,如果 newReg 变得非常大,程序在函数中传递、重新创建、传回和销毁临时类参数时可能会产生速度开销。这种速度开销担心不是问题吗?

在更复杂的类的情况下,我可能会更加 OOP,并且只将类的那些参数传递给需要处理的方法。我开始使用这种方法,但编码很快变得混乱,并在主程序流中添加了额外的代码(从类中提取数据并将函数返回的数据插入回类中),我希望保持简洁和易读。

我是否应该避免使用我喜欢的选项 1 方法而选择选项 2?我尝试了选项 3 方法,但它似乎创建了更复杂的编码。建议表示赞赏。

class Register:
    def __init__(self,dd,mm,yy):
        self.d = dd
        self.m = mm
        self.y = yy
        self.people = []

class Person:
    def __init__(self,name,ident):
        self.name = name
        self.ident = ident

def inputPeople():
    name =""
    print("enter 'end' as name to finish update")
    while name != "end":
        name = input("enter name:")
        ID = input ("enter ID:")
        if name == "end":
            return
        newperson = Person(name,ID)
        newReg.people.append(newperson)

def outputRegister():
    print("register date: %s/%s/%s" % (newReg.d, newReg.m, newReg.y))
    for element in newReg.people:
        values = vars(element).values()
        print('|'.join("%10s" % item for item in values))
    return

#main prog option 1: treat newReg globally when calling functions
newReg = Register(12,5,17)
choice =""
while choice != "E":
    choice = input("enter U to update, L to list, E to exit")
    if choice == "U":
        inputPeople()
    if choice == "L":
        outputRegister()
print("session over")

#main prog option 2: pass newReg as a parameter to the functions
newReg = Register(12,5,17)
choice =""
while choice != "E":
    choice = input("enter U to update, L to list, E to exit")
    if choice == "U":
        newReg = inputPeople(newReg) # and modify fn codes accordingly
    if choice == "L":         # to handle newReg as a parameter
        outputRegister(newReg)# rather than a class object in 
print("session over")         # the main body

【问题讨论】:

标签: function class parameter-passing


【解决方案1】:

由于这两个选项都有效,这是一个风格和观点的问题,但我个人认为 1 适合小型脚本,但改进的 2 是大型应用程序的方式。

您在两个选项中的函数 inputPeople() 几乎都受限于在具有附加接口的人员字段的实例上进行操作。这并不理想。使用 OOP,最好让您传入的对象有一个用于添加人员的接口,例如 addPerson(Person)。

这意味着您的 inputPeople 函数不需要知道注册表用于存储人员的数据结构。此外,只要容器具有 addPerson(Person) 方法,就可以更轻松地重用该函数并传入其他类型的人员容器。

使用选项 1,您的 inputPeople 函数只能用于 newreg 而不能用于其他也可能有人员的事物。

【讨论】:

  • 嗨,Alwyn - 你的评论给了我灵感。我在实际应用程序中给出了我写的第二个函数,我认为它可以重写为 3 个子函数(带参数传递),每个子函数将来都可以在其他地方重用。我对这种修改后的方法更满意。感谢您的时间和分享您的想法。它有帮助!
  • 谢谢加里。我开始研究 OOP,当时它还是 Turbo Pascal 5 的 hack,很长一段时间我都了解 OOP 的结构和功能集,但我错过了 OOP 的重要部分,即如何使用此功能来实现目标超越显而易见的。然后我阅读了 Bert Bates 的 Head First Design Patterns,虽然这些模式很简洁,但真正让我印象深刻的是您如何使用 OOP 的属性来实现清晰代码的目标,同时保持您的代码可维护、易于重用和扩展。您的目标定义了您的代码以及您如何应用工具
猜你喜欢
  • 2019-03-29
  • 2016-10-28
  • 2013-02-12
  • 1970-01-01
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
相关资源
最近更新 更多