我的Python代码中有许多非常相似的函数,如下所示:
self.thisTransaction.amount = [NSDecimalNumber decimalNumberWithString:self.amountField.text locale:NSLocale.currentLocale];
NSLog(@"1 thisTransaction.amount is %@",self.thisTransaction.amount);
// Inverts the transaction amount
NSDecimalNumber * invertedMultiplier = [NSDecimalNumber decimalNumberWithString:@"-1"];
self.thisTransaction.amount = [self.thisTransaction.amount decimalNumberByMultiplyingBy:invertedMultiplier];
NSLog(@"2 thisTransaction.amount is %@",self.thisTransaction.amount);
有没有办法避免在不影响执行速度的情况下重复定义这些函数?
答案 0 :(得分:6)
你不需要一个宏;函数是第一类对象,可以动态构建:
def make_callback(m_type, other_type, *attrs):
def callback(msg):
m = m_type(msg)
a = other_type()
for attr in attrs:
setattr(a, attr, getattr(m, attr))
pub2.publish(a)
return callback
callback1 = make_callback(MsgX, msg_type_a, 'x')
callback2 = make_callback(MsgY, msg_type_b, 't', 'u')
如果您愿意以某种方式标准化类型,您可以使这更简单。例如,如果这些other_type
内容中的每一个都是namedtuple
- ish类型(具有_fields_
或__slots__
或某些其他可迭代属性名称的内容):
def make_callback(m_type, other_type):
def callback(msg):
m = m_type(msg)
a = other_type()
for attr in other_type._fields_:
setattr(a, attr, getattr(m, attr))
pub2.publish(a)
return callback
callback1 = make_callback(MsgX, msg_type_a)
callback2 = make_callback(MsgY, msg_type_b)
或者,如果msg_type
只知道如何从MsgTypes
构建自己:
def make_callback(m_type, other_type):
def callback(msg):
m = m_type(msg)
a = other_type(m)
pub2.publish(a)
return callback
callback1 = make_callback(MsgX, msg_type_a)
callback2 = make_callback(MsgY, msg_type_b)
或者,如果MsgTypes
知道如何将自己转换为msg_types
(甚至可能是动态生成的):
def make_callback(m_type):
def callback(msg):
m = m_type(msg)
pub2.publish(m.to_other_type())
return callback
callback1 = make_callback(MsgX, msg_type_a)
callback2 = make_callback(MsgY, msg_type_b)
等等。所有基本的OO设计都是在适当的时候用Python提供的(很难知道你的玩具示例中哪些是合适的),但你有很多反射/动态功能可以回到它们不适用的时候。
这会影响表现吗?
好吧,你要么循环遍历2个事物的列表,要么添加额外的函数调用,这需要几纳秒。但这真的很重要吗?如果是这样,你几乎肯定想要改变你的设计,以便msg_type
类型可以更便宜地构建(例如,在一次调用中),等等,并且在这样做时,你可以适应某些东西这使得这部分也更容易优化。
答案 1 :(得分:2)
没有宏,但您可以创建一个定义另一个函数并返回它的函数:
def make_callback(msg_type, msg_type_func, attrs_to_copy):
def callback(msg):
m = msg_type(msg)
x = msg_type_func()
for attr in attrs_to_copy:
setattr(x, attr, getattr(m, attr))
pub2.publish(x)
return callback
然后你会做类似的事情:
callback1 = make_callback(MsgX, msg_type_a, ['x'])
callback2 = make_callback(MsgY, msg_type_b, ['t', 'u'])
根据逻辑的复杂程度以及不同函数的确切变化,您可能希望编写一个将回调功能分解为部分的类(例如,“设置属性”步骤和“发布步骤” “)并提供一个单独的”go“方法来执行它们。此外,如果您知道哪些组合有意义(即,您知道MsgX
始终与msg_type_a
一起使用),那么您可以在某个字典中将该信息显式化,并使用该字典来派生各个部分来自一个或几个“关键”值的呼叫。
答案 2 :(得分:1)
听起来像是在课后,它们允许您将方法和变量分配给结构相同的对象