我正在研究一段科学代码,我们希望在其中实现几个求解器并进行比较。我们正在使用一个配置文件,我们可以在其中声明我们希望应用的解算器的名称。由于我们不断添加新的解算器,我将它们包含在一个类中,以便我们可以从配置文件中提取名称并将其应用于getattr
,而不必在代码之外添加任何新内容。求解器方法本身。除了这个类中的求解器之外,我没有实现任何属性或任何方法。
如果所选解算器不存在,我也会实现错误消息。整个块看起来像这样:
try:
solver = getattr(Solvers,control['Solver'])
except AttributeError:
print('\n Invalid Solver Choice! Implemented solvers are: \n' \
+ str(set(dir(Solvers)) - set(dir(Empty)))) # Implemented solvers
raise
solver(inputs) # Call the desired solver
这很方便,因为它通过添加新方法自动更新我们的错误处理。我的问题与那里的错误信息有关。具体来说,我想返回已实施解算器的列表以及已实现解算器的仅。
仅仅列出dir(Solvers)
的输出是不够的,因为这包括许多其他方法,如__init__
。同样,我无法设置 - 减去dir(object)
的结果,因为这仍然会返回一些额外的内容,例如__dict__
和__module__
。这就是为什么我有类Empty,它只是:
class Empty:
pass
我想知道是否存在比kludgey Empty
类更优雅的方式来实现它。
答案 0 :(得分:2)
一种方法是:
set(A.__dict__) - set(type.__dict__)
但是,它仍会返回__weakref__
。相反,您可以使用:
set(A.__dict__) - set(type("", (), {}).__dict__)
它将您的班级与type("", (), {})
进行比较。这会创建一个新的类对象,就像您的Empty一样,但是更加微妙。对于示例类:
>>> class A: pass
...
它给出了:
>>> set(A.__dict__) - set(type("", (), {}).__dict__)
set()
并且:
>>> class B:
... def f(self): pass
...
它返回:
>>> set(B.__dict__) - set(type("", (), {}).__dict__)
{'f'}
您可以使用dir
来执行此操作:
>>> set(dir(B)) - set(dir(type("", (), {})))
{'f'}
答案 1 :(得分:1)
显式优于隐式,您可能希望在类中使用非求解器方法。最简单明确但干燥的解决方案是只使用装饰器来标记哪些方法应被视为“解算器”方法:
def solver(fun):
fun.is_solver = True
return fun
class Solvers(object):
@solver
def foo(self):
return "foo"
@solver
def bar(self):
return "bar"
@classmethod
def list_solvers(cls):
return [name for name, attr
in cls.__dict__.items()
if getattr(attr, "is_solver", False)]