将类作为函数参数传递,并在函数内反复重置类

时间:2018-10-04 14:03:01

标签: python class

在我的python脚本中,我定义了一个类似于以下(公认的)伪造类的类:

import copy


class Example:

    def __init__(self, a, b):

        self.a = a
        self.b = b

        self.__default__ = copy.deepcopy(self.__dict__)

        self.t = 0
        self.d = False

    def do(self):

        self.a += self.b - self.t
        self.t += 1
        if self.t == self.b:
            self.d = True
        return self.a

    def reset(self):

        self.__init__(**self.__default__)

现在,我想将此类的实例传递给我的主函数,并反复将该实例重置为其默认状态。尽管查看了herehereherehere,但我还是无法理解。下面的工作示例提供了所需的结果,但仍在主函数中显式重置了该实例。功能失调的示例是我尝试使用reset方法使其正常工作的众多尝试之一。

# working example:
def main(x):

    agg = []
    for i in range(x):
        klass = Example(1, 3)
        while not klass.d:
            a = klass.do()
            agg.append(a)
    return agg

# dysfunctional example:
def main2(klass, x):

    agg = []
    for i in range(x):
        klass.reset()
        while not klass.d:
            a = klass.do()
            agg.append(a)
    return agg

然后main(5)给出

res = main(5)
print(res)
>>> [4, 6, 7, 4, 6, 7, 4, 6, 7, 4, 6, 7, 4, 6, 7]

ex = Example(1, 3)  # default state
res = main2(ex, 5)
print(res)

引发错误:TypeError: __init__() got an unexpected keyword argument '__default__'

由于我想避免由于各种原因而不得不在主脚本中重新实例化该类,因此,如果有人可以通过reset方法帮助我,我将不胜感激。

3 个答案:

答案 0 :(得分:2)

那又怎么样呢?

class Example:

    def __init__(self, *args, **kwargs):
        """This stores the default state then init the instance using this default state"""
        self.__default_args__ = args
        self.__default_kwargs__ = kwargs
        self.init(*args, **kwargs)

    def do(self):
        """Do whatever you want """
        self.a += self.b - self.t
        self.t += 1
        if self.t == self.b:
            self.d = True
        return self.a

    def init(self, a, b):
        """Inits the instance to a given state"""
        self.a = a
        self.b = b
        self.t = 0
        self.d = False
        return self

    def reset(self):
        """Resets the instance to the default (stored) state"""
        return self.init(*self.__default_args__, **self.__default_kwargs__)

答案 1 :(得分:1)

这是使用上下文管理器的实现:

class Example:
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.t = 0
        self.d = False

    def do(self):
        self.a += self.b - self.t
        self.t += 1
        if self.t == self.b:
            self.d = True
        return self.a

    def __enter__(self):
        self._a = self.a
        self._b = self.b

    def __exit__(self, *args):
        self.t = 0
        self.d = False
        self.a = self._a
        self.b = self._b

def main2(klass, x):
    agg = []
    for i in range(x):
        with klass:
            while not klass.d:
                a = klass.do()
                agg.append(a)
    return agg


ex = Example(1, 3)
res = main2(ex, 5)
print(res)

答案 2 :(得分:0)

一种可重用的方法是实现要继承的Resettable类。

可重置

class Resettable:
    def __init__(self, *args, **kwargs):
        self.__args__ = args
        self.__kwargs__ = kwargs

    def reset(self):
        self.__init__(*self.__args__, **self.__kwargs__)

用法

使用property定义一个完全依赖于其他属性的属性也可以使重置过程更加顺畅。对于唯一需要及时往返的国家来说,拥有单一事实来源的想法通常是有用的范例。

class Example(Resettable):
    def __init__(self, a=0):
        self.a = a
        super().__init__(a)

    def do(self):
        self.a += 1
        return self.a

    @property
    def d(self):
        return self.a > 3 # or any other condition

def main(instance, x):
    agg = []
    for _ in range(x):
        instance.reset()
        while not instance.d:
            a = instance.do()
            agg.append(a)
    return agg

print(main(Example(), 3)) # [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]

Resettable类的基本假设是,传递给构造函数的参数包含重置所需的所有信息,使用属性使该假设更容易满足。