Python officially recognizes名称空间作为一种“鸣叫的好主意”,我们应该“做更多”。名称空间的一个好处是它们的分层表示,它将代码组织成相关的部分。有没有一种优雅的方法将python类方法组织成相关的部分,就像组织分层命名空间一样 - 特别是为了完成制表符的目的?
我的一些python类不能拆分成更小的类,但是附加了许多方法(很容易超过一百)。我也发现(我的代码的用户告诉我)找到有用方法的最简单方法是使用制表符完成。但是由于有这么多方法,这变得笨拙,因为提供了大量选项 - 通常按字母顺序排列,这意味着密切相关的方法可能位于这个庞大列表的完全不同的部分。
通常,存在非常不同的密切相关方法组。例如,我有一个类,其中几乎所有方法都属于四个组之一:
并且io
组可能具有读取和写入子组,其中存在用于读取或写入的文件类型的不同选项,然后在查看元数据时涉及一些其他方法。在很小程度上,我可以在我的方法名称中使用下划线来解决这个问题。例如,我可能有像
myobject.io_read_from_csv
myobject.io_write_to_csv
这有助于分类,但是很难看,仍会导致难以处理的制表符完成列表。如果第一个选项卡完成列表只有上面列出的四个选项,那么我更喜欢它,然后当选择其中一个选项时,下一个选项卡将显示其他选项。
对于一个稍微更具体的例子,这里是我为我的班级考虑的层次结构的部分列表:
myobject.io
myobject.io.read
myobject.io.read.csv
myobject.io.read.h5
myobject.io.read.npy
myobject.io.write
myobject.io.write.csv
myobject.io.write.h5
myobject.io.write.npy
myobject.io.parameters
myobject.io.parameters.from_csv_header
myobject.io.parameters.from_h5_attributes
...
...
myobject.statistics
myobject.statistics.max
myobject.statistics.max_time
myobject.statistics.norm
...
myobject.transformations
myobject.transformations.rotation
myobject.transformations.boost
myobject.transformations.spatial_translation
myobject.transformations.time_translation
myobject.transformations.supertranslation
...
myobject.symmetries
myobject.symmetries.parity
myobject.symmetries.parity.conjugate
myobject.symmetries.parity.symmetric_part
myobject.symmetries.parity.antisymmetric_part
myobject.symmetries.parity.violation
myobject.symmetries.parity.violation_normalized
myobject.symmetries.xreflection
myobject.symmetries.xreflection.conjugate
myobject.symmetries.xreflection.symmetric_part
...
...
...
我可以想象解决此问题的一种方法是在我的主IO
类中创建类Statistics
,MyClass
等类,其唯一目的是存储对{的引用{1}}并提供它所需的方法。然后,主类将具有myobject
方法,这些方法只返回那些低级类的实例,然后选项卡完成应该起作用。这有意义吗?例如,在ipython中提供制表符完成是否可行?这会导致循环引用问题吗?还有更好的方法吗?
答案 0 :(得分:0)
看起来我在类中定义类的天真建议确实适用于ipython的tab-completion并且没有任何循环问题。
这是概念验证代码:
class A(object):
class _B(object):
def __init__(self, a):
self._owner = a
def calculate(self, y):
return y * self._owner.x
def __init__(self, x):
self.x = x
self._b = _B(self)
@property
def b(self):
return self._b
(事实上,如果我使用self.b = _B(self)
会更简单,我可以跳过property
,但我喜欢这样,因为它阻止从类外部覆盖b
。此外,这表明这种更复杂的情况仍然有效。)
因此,如果我创建a = A(1.2)
,我可以点击a.<TAB>
并获得b
作为完成,然后a.b.<TAB>
建议calculate
作为完成。到目前为止,我的简短测试中没有遇到任何有关此结构的问题,并且对代码的更改不是很大 - 只需将._owner
添加到很多方法代码中。