智能自动C代码生成器,支持Python中的嵌套if
我正在用Python自动生成C++代码,特别是我需要从一系列事件中选择一些事件。我声明了一些选择:
selectionA = Selection(name="selectionA", formula="A>10")
selectionB = Selection(name="selectionB", formula="cobject->f()>50")
selectionC = selectionA * selectionB # * means AND
这段代码会生成C++代码:
for(...) { // cicle on events
event = GetEvent(i);
bool selectionA = A>10;
bool selectionB = cobject->f()>50;
bool selectionC = (A>10) and (cobject->f()>50);
if (selectionA) { histo_selectionA->Fill(event); }
if (selectionB) { histo_selectionB->Fill(event); }
if (selectionC) { histo_selectionC->Fill(event); }
}
这并不是很聪明,因为更聪明的代码应该是:
bool selectionC = selectionA and selectionB
这个问题看起来简单,但实际上并不简单,因为我有100多个基础选择(比如selectionA
或selectionB
)和300多个派生选择,当然,派生选择可以从其他派生选择中派生出来。显而易见的派生选择并不是通过常规模式从基础选择中派生出来的。
我知道这个问题很难回答,但有没有人能给我一些提示?比如:真的有必要写聪明的代码吗?我的意思是,编译器不能优化这段代码吗?
4 个回答
作为我评论的补充,我觉得你甚至不需要我之前提到的那个跟踪变量。为什么不试试这个呢?
import string
class Selection:
selections = []
letters = string.letters[26:] + string.letters[:26]
def __init__(self, name, formula):
self.name = name
self.formula = formula
Selection.selections.append(self)
def __mul__(self, selection):
name = 'selection' + letters[len(selections)]
return Selection(name, self.name + ' and ' + selection.name)
@classmethod
def generate(c):
code = []
for selection in c.selections:
code.append('bool ')
code.append(selection.name)
code.append(' = ')
code.append(selection.formula)
code.append(';\n')
code.append('\n')
for selection in c.selections:
code.append('if (')
code.append(selection.name)
code.append(') { histo_')
code.append(selection.name)
code.append('->Fill(event); }\n')
return ''.join(code)
当然,这个方法只适用于你只有52个选择对象的情况,但这个限制是因为这个类只生成像selection[A-Za-z]这样的名称。
编译器可能会对这段代码进行优化,但如果你有成百上千个复杂的表达式相互依赖,我怀疑效果会好到哪里去。
不过更基本的问题是:你真的需要优化吗?计算机运行得很快,如果你不经常执行那段代码,cobject->f()>50
运行一次和十次可能没什么太大区别。
另一方面,如果cobject->f()
有副作用(比如,它会打印一些东西),那么编译器就不会优化掉重复的调用,你需要确保在生成的代码中,它只在你希望打印东西的次数被调用。
最好的解决办法是,如果你的Selection
类在作为派生定义的一部分使用时,能够直接输出name
而不是formula
。这有多难,取决于你生成代码的方式。
编译器可能无法优化这段代码,部分原因是 cobject->f()
可能会有一些编译器看不到的副作用。
你可以通过将你的布尔值声明为 const
来稍微帮助一下优化。
另外,看起来你已经在重载运算符来组合选择了。所以,想要让组合选择使用其组成部分的名称,而不是表达式,这应该不会太难。这可以为你做一些优化,并且如果你把选择的布尔值声明为 const
,编译器可能会进一步优化。
你还需要注意,在Python中创建选择对象时,要按照相同的顺序来初始化 bool
标志。这可以确保每个 bool
在后续使用之前都已经声明和初始化。你可以通过在Python的 Selection
类中创建一个列表,并在 __init__
方法中将新的 Selection
添加到这个列表来实现。当然,如果你创建了 Selection
对象后又把它们丢掉,那可能会有问题。但如果你把它们都保留着,那就没问题了。