在Python中重置类的首选方法

时间:2017-08-21 13:53:18

标签: python python-3.x class

基于this post on CodeReview

我上课了 Python(3)中的javax.validation.constraints.NotNull,当然包含Foo方法。这个类会触发一些提示并完成它的工作。假设我希望能够重置__init__(),以便我可以重新开始这个过程。

什么是首选实施?

再次调用Foo方法

__init__()

或创建新实例?

def reset(self):
    self.__init__()

如果多次调用def reset(self): Foo() ,我不确定创建Foo的新实例是否会留下可能影响性能的任何内容。另一方面,reset可能会产生副作用,如果不是__init__()中(重新)定义了所有属性。

有没有首选的方法呢?

3 个答案:

答案 0 :(得分:7)

两者都是正确的,但语义没有以相同的方式实现。

为了能够重置一个实例,我会写这个(我更喜欢从__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__中完成,但第二种方式是在创建时使用{{1}自定义的特殊类所必需的},例如不可变类。

但要注意,这段代码:

__new__

执行您想要的操作:它只会创建一个新实例,并立即将其删除,因为它将在方法结束时超出范围。甚至def reset(self): Foo() 只会在方法结束时设置本地引用,这些引用会超出范围(并且新实例被销毁)。

答案 1 :(得分:3)

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

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实例,并且创建一个新的将取消引用前一个。

答案 2 :(得分:0)

正如其他人所说,您不需要重置课程。但是如果你真的想要它,你可以使用一个工厂函数,每次调用都会返回一个新类。

def make_Foo():
    class Foo():
        VALUE = 1
    return Foo

Foo = make_Foo()
Foo.VALUE = 2
print(Foo.VALUE)  # prints 2

Foo = make_Foo()  # reset
print(Foo.VALUE)  # prints 1