【问题标题】:I need to pickle an array of (hardly pickable) class members我需要腌制一组(很难挑选的)班级成员
【发布时间】:2015-07-13 20:14:56
【问题描述】:

我有一些使用__reduce__ 腌制的类实例。这些类有我在另一个数组中收集的成员。我需要腌制这个数组,但我找不到正确的方法。 只是为了澄清一些事情,想象一下我有代表正方形、矩形和圆形的类。我创建了一些实例:

A=Square(10)
B=Rectangle(5,10)
C=Circle(6)

我可以腌制列表

classes=[A, B, C] 

但我需要一种方法来腌制这个类实例属性数组

dimensions=[A.side, B.y, C.diameter]

保留对原始对象的引用,以便如果一个对象发生更改,则相关属性会发生更改:假设我调用C.grow(2),我希望得到dimensions[2]=12

为了解决这个问题,我现在腌制这本字典:

d={   classes: [A, B, C],
   dimensions: [(A,'side'), (B,'y'), (C,'diameter')] }

但我认为这是一个非常糟糕的解决方案。

感谢任何建议。

【问题讨论】:

  • ABC 不是类,它们是类实例。如果你有他们的列表,instances = [A, B, C],那么,即使在腌制/取消腌制之后,你应该能够访问instances[0].sideinstances[1].y等。
  • 您的代码难以理解,因为它不遵循PEP 8 Python 编码准则,即只大写类型名称(如Square),但只使用小写变量名。跨度>
  • @martineau 我的问题是,在 unpickling 之后,我不知道 instances 的每个项目需要什么成员......这就是为什么我也腌制 尺寸列表。
  • 然后您需要以某种方式将类型信息以及实例存储在列表中,或者确保所有实例都有一个可以调用的通用方法来获取所需信息。最后,您可以使用 instance[i],__class__ 检查每个实例的类型以了解要访问的属性,但这不是非常面向对象的。

标签: python pickle


【解决方案1】:

如果您有 A.side 之类的 int 类型,则保留对象原始引用的唯一方法是将其保存在列表或它自己的类中。

例如,您可以这样做:

class Value:
    def __init__(self, val):
        self.value = val

现在,您可以创建 SquareRectangleCircle,以便它们对每个变量使用 Value 类。

class Square:
    def __init__(self, side_length):
        self.side = Value(side_length)

然后在像dimensions = [A.side, ...]这样的维度上使用它

注意,现在 A.side 是一个类 - 使用 print(A.side) 无法查看该值,但使用 print(A.side.value) 可以查看该值

【讨论】:

  • side 在我的示例中是一个整数,但在实际代码中它仍然是一个类。那个类来自一个库,它是不可选择的,我不想修改那个库。
【解决方案2】:

我想出了这个解决方案:

class AttributeWrapper(object):
    def __init__(self, obj, attribute):
        object.__setattr__(self, 'ref_obj', obj)
        object.__setattr__(self, 'ref_attribute', attribute)

    def __getattr__(self,attr):
        return object.__getattribute__(self,'ref_obj').__getattribute__(object.__getattribute__(self,'ref_attribute')).__getattribute__(attr)

    def __setattr__(self,attr,value):
        object.__getattribute__(self,'ref_obj').__getattribute__(object.__getattribute__(self,'ref_attribute')).__setattr__(attr,value)
        return value

我认为这不是理想的解决方案,但至少,我不必更改其他类(示例中为 Square、Rectangle、Circle)。

感谢大家的帮助。

【讨论】:

    【解决方案3】:

    如果问题是您的类方法无法被腌制,那么您可以尝试dill。它通常可以腌制类实例、类方法和实例方法。

    >>> import dill
    >>> 
    >>> class Square(object):
    ...   def __init__(self, side):
    ...     self.side = side
    ... 
    >>> class Rectangle(object):
    ...   def __init__(self, x, y):
    ...     self.x = x
    ...     self.y = y
    ... 
    >>> class Circle(object):
    ...   def __init__(self, diameter):
    ...     self.diameter = diameter
    ... 
    >>> a = Square(10)
    >>> b = Rectangle(5, 10)
    >>> c = Circle(6)
    >>> 
    >>> dimensions = [a.side, b.x, b.y, c.diameter]
    >>> _dim = dill.dumps(dimensions)
    >>> 
    >>> dim_ = dill.loads(_dim)
    >>> dim_
    [10, 5, 10, 6]
    >>> 
    

    【讨论】:

      猜你喜欢
      • 2020-12-26
      • 1970-01-01
      • 2020-09-11
      • 1970-01-01
      • 2021-11-09
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 2012-04-23
      相关资源
      最近更新 更多