在 Python 中重置类的首选方法

新手上路,请多包涵

基于 CodeReview 上的这篇文章

我在 Python (3) 中有一个类 Foo ,它当然包括一个 __init__() 方法。这个类会触发几个提示并执行它的操作。假设我希望能够重置 Foo 这样我就可以重新开始整个过程。

什么是首选实施?

再次调用 __init__() 方法

def reset(self):
    self.__init__()

或创建一个新实例?

 def reset(self):
    Foo()

我不确定创建 Foo 的新实例是否会留下任何可能影响性能的东西,如果多次调用 reset 。另一方面 __init__() 如果并非所有属性都在 __init__() 中定义(重新),则可能会产生副作用。

有没有更好的方法来做到这一点?

原文由 JAD 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

两者都是正确的,但语义的实现方式不同。

为了能够重置一个实例,我会写这个(我更喜欢从 __init__ 调用自定义方法而不是相反,因为 __init__ 是一种特殊方法,但这主要是一个口味问题):

 class Foo:
    def __init__(self):
        self.reset()
    def reset(self):
        # set all members to their initial value

你这样使用它:

 Foo foo      # create an instance
...
foo.reset()  # reset it

从头开始创建一个新实例实际上更简单,因为该类不必实现任何特殊方法:

 Foo foo      # create an instance
...
foo = Foo()  # make foo be a brand new Foo

如果旧实例未在其他任何地方使用,它将被垃圾回收

这两种方式都可用于 普通 类,其中所有初始化都在 __init__ 中完成,但第二种方式需要在创建时使用 __new__ 自定义的特殊类,例如不可变类.


但请注意,这段代码:

 def reset(self):
    Foo()

不会 做你想做的事:它只会创建一个新实例,并立即删除它,因为它会在方法结束时超出范围。即使是 self = Foo() 也只会设置本地引用,这同样会在方法结束时超出范围(并且新实例被销毁)。

原文由 Serge Ballesta 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以将您使用的实例保存在类属性中。每当您想重置类时,请将新实例重新分配给该属性。以下是我将如何实施这种方法:

 class Foo:
    instance = None    # The single instance

    def __init__(self, ...):
        # Initialize the instance if Foo.instance does not exist, else fail
        if type(self).instance is None:
            # Initialization
            type(self).instance = self
        else:
            raise RuntimeError("Only one instance of 'Foo' can exist at a time")

    @classmethod
    def reset(cls):
        cls.instance = None        # First clear Foo.instance so that __init__ does not fail
        cls.instance = Foo(...)    # Now the initialization can be called

然后,您只需引用 Foo.instance 即可访问该实例。

我选择将 reset 作为类方法,因此由 @classmethod 。使用此装饰器,可以通过调用 Foo.reset() 重置实例,并且 cls 参数将自动传递给该方法。

与您建议的方法相比,我更喜欢这种方法(或多或少是单例模式),因为在您的情况下,拥有 Foo 的单个实例似乎是合乎逻辑的,因为您想 重置 它。因此,我发现“强制”使用单个实例相当直观。

另一方面,你可以在类之外有一个实例,并使用 reset 实例方法,定义:

 def reset(self):
    self.__init__()

但这可能效果不佳。假设您想在 __init__ 方法之外设置属性。调用 __init__ 不会重置这些属性。因此,您的实例不会按预期重置。现在,如果您拥有一个实例并将其重新分配给一个全新的实例,您可以确定它绝对是干净的。

关于你所说 的“创建一个新实例” ,这或多或少是我选择的,但问题是在哪里存储它。我认为在课堂上保持温暖是有意义的。

顺便说一下,这个解决方案不应该有任何性能问题(如“内存泄漏”),因为一次只引用一个 Foo 实例,创建一个新实例将取消引用上一个。

原文由 Right leg 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题