我有一个有点复杂的类Thing
,以及一个相关联的mixinIterMixin
(使类成为可编辑的)…和一个funky
方法,它接收我的类的一个实例作为参数。在
事实上,我正试图将一组参数捆绑成单个对象,传递给下面的funky
函数之外的多个外部函数。一种参数对象设计模式。。。在
class IterMixin():
def __iter__(self):
for attr, value in self.__dict__.items():
yield attr, value
class Thing(IterMixin):
def __iter__(self, foo=None, bar=None, baz=999):
if foo is None:
self.foo = {}
else:
self.foo = foo
if bar is None:
self.foo = {}
else:
self.bar = bar
self.baz = baz
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, data)
self._foo = self.parser(data)
@property
def bar(self):
return self._bar
@bar.setter
def bar(self, more_data)
self._bar, self.baz = self.another_parser(more_data)
def parser(self, data):
...do stuff...
return foo
def another_parser(self, more_data):
...do add'l stuff...
return bar, baz
关于funky
函数,在一个完全不同的模块中,通过Thing
类,我想将Thing
的属性(foo
、bar
)和baz
)作为一个参数传递给funky
函数,如下所示:
问题:
如果我不使属性foo
和bar
私有的setter(例如,通过self._foo
)即下划线的方式——那么我在类初始化期间引发无限递归……因为这些属性的__init__
和setter反复循环并反复调用自己。为了避免这种情况,我使用了@property
修饰符,并在设置foo和bar时将它们“私有化”。在
但是,当我传递Thing
类的实例,并通过splat或asterick将其属性解压为funky
函数中的参数,如果我反省这些属性的结果键,我仍然得到_foo
和_bar
。我好像无法摆脱下划线。(换句话说,我得到了Thing
的“私有化”属性名。)
funky
的biz逻辑需要解压后的值没有任何下划线。在
为什么会发生这种情况(拆包时的下划线)?我该怎么解决这个问题?有没有一种更优雅的方法可以在不私有化任何东西的情况下初始化foo和bar属性?或者用一种更python的方式将Thing
类中的所有属性传递给我的funky
函数?在
首先,您遇到了一个大问题,它甚至会阻止您看到您请求帮助的问题:您的
Thing
类定义了一个__iter__
方法,该方法没有super
,也没有yield
或return
任何东西。希望这部分只是一些打字错误,你知道如何修复它来做你真正想做的事情。在不,你要问的问题是:
尝试打印出实例的
^{pr2}$__dict__
。或者,最好是这样一个最小的例子:输出是
{'_foo': 2}
。在您试图通过给属性指定私有名称并将其放在属性后面来隐藏属性,但是之后您又在属性的背后直接查看了真正属性所在的
__dict__
。在还有什么能在那里?实际的
_foo
必须存储在每个实例的某处。另一方面,foo
实际上不是一个值,它是一个使用私有属性的getter/setter,因此它不会存储在任何地方。在如果您真的希望使用反射来查找实例上的所有“公共值”,可以执行以下操作:
然而,我认为这将是更好的而不是这样做。更简单、更干净的选项包括:
_fields = 'foo', 'bar', 'baz'
,并让基类迭代_fields_
。在attrs
(或者,如果您不是OP,而是将来阅读本文的人,他可以依赖3.7+,dataclass
)为您完成这项工作。在dict
构造(在这一点上,作为映射更简单)之外,对任何事情都没有用。另外,混音并不能帮你解决困难的部分。Whatever you actually need to do, ask for help on how to do that, instead of how to make this code that shouldn't work work anyway.相关问题 更多 >
编程相关推荐