如何避免Python中类似的函数定义?

时间:2015-05-27 22:17:26

标签: python function

我的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);

有没有办法避免在不影响执行速度的情况下重复定义这些函数?

3 个答案:

答案 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)

听起来像是在课后,它们允许您将方法和变量分配给结构相同的对象