代码之家  ›  专栏  ›  技术社区  ›  apitsch

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

  •  0
  • apitsch  · 技术社区  · 8 年前

    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__)
    

    现在,我想把这个类的一个实例传递给我的main函数,并反复地将这个实例重置为它的默认状态。尽管看了一眼 here , here , here here ,我无法继续。下面的工作示例给出了所需的结果,但显式地重置了main函数中的实例。这个功能失调的例子是我多次尝试使用 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__'

    因为我不想因为不同的原因在主脚本中重新实例化这个类,如果有人能帮我解决这个问题,我将不胜感激 方法。

    3 回复  |  直到 8 年前
        1
  •  2
  •   Guillaume    8 年前

    这样怎么样:

    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__)
    
        2
  •  1
  •   bboumend    8 年前

    下面是一个使用上下文管理器的实现:

    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)
    
        3
  •  0
  •   Olivier Melançon iacob    8 年前

    一种可重用的方法是实现 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]
    

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