【问题标题】:Is there a way to get class constructor arguments by self inspection?有没有办法通过自检来获取类构造函数参数?
【发布时间】:2017-07-13 23:03:01
【问题描述】:

我有一组类,我想在 JSON 和 mongodb 数据库之间进行序列化。我看到的最有效的方法是编写方法来序列化为字典,然后使用内置方法来获取/从存储中获取。 (Q1:这个结论真的有效吗,还是有更好的办法?

因此,要将我的类的实例导出到字典,我可以使用 self.dict。在我的例子中,这些类是嵌套的,所以它必须是递归的,很好。现在我想把它读回来......但是如果我的类有一个非平凡的构造函数,我会被困住。考虑:

class MyClass(object):
    def __init__(self, name, value=None):
        self.name = name
        self._value = value
    @property
    def value(self):
        return self._value

a = MyClass('spam', 42)
d = a.__dict__ #has {'name':'spam', '_value':42}
#now how to unserialize?
b = MyClass(**d) #nope, because '_value' is not a valid argument
c = MyClass(); c.__dict__.update(d)  #nope, can't construct 'empty' MyClass

我不想编写一个忽略未知参数的构造函数,因为我讨厌浪费时间试图找出一个类忽略某些参数以发现名称中有错字的原因。而且我不想删除所需的参数,因为这可能会导致其他地方出现问题。

那么我该如何解决我为自己制造的这个烂摊子呢?

  • 如果有办法绕过类的构造函数并创建一个空的 对象,这可能有效,但如果在__init__ 中完成了任何有用的工作,我会失去它。 (例如,参数的类型/范围检查)。
  • 在我的例子中,这些类在构造后不会改变(它们定义了很多有用的方法,并且有一些缓存)。所以如果我可以从字典中提取构造函数参数,我会做得很好。有没有不重复所有构造函数参数的方法?

【问题讨论】:

  • 你最好创建工厂方法来反序列化每个类型,这样类型就可以实际控制如何构造对象。否则,您只是在外面,在您尝试填写正确的值时猜测该黑盒类型是如何工作的。 – 想象一下,如果 value 属性返回 self._value * 2
  • 你是否愿意接受这样的黑客攻击:ideone.com/R9T2Nd
  • @poke 我不明白你评论的最后一部分;只要属性/方法不改变任何属性,我为什么要关心它们进行序列化?
  • @AshwiniChaudhary 哇。覆盖__new__ 绝对不是我想过的。更好的办法是让它成为一个装饰器,并在备用构造函数中获取字典。关键是object.__new__(cls)

标签: python json serialization constructor


【解决方案1】:

我不知道这是否只是一个微不足道的例子,但我看不到属性value(没有双关语)的价值。如果您直接从 __init__ 分配 value 参数,我的意思是。在这种情况下,只需使用一个简单的属性就可以解决您的问题。

但如果由于某种原因你真的需要一个属性,只需去掉键中的破折号:

class MyClass(object): 
    Pdef __init__(self, name, value=None):
        self.name = name 
        self._value = value 
    @property 
    def value(self): 
        return self._value 

a = MyClass('spam', 42)
d = {k.strip('_'): v for k, v in a.__dict__.items()}
b = MyClass(**d)

【讨论】:

  • value 这里确实是一个微不足道的例子,尽管这给出了一个有点有用的“只读”属性。要点是构造函数参数并不都直接映射到具有相同名称的“公共”属性。过滤下划线的技巧对于我正在做的事情可能很简单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-23
  • 2011-10-08
  • 2011-07-28
  • 1970-01-01
相关资源
最近更新 更多