如何避免Python中类似的函数定义?
我的Python代码中有一系列非常类似的函数,如下所示:如何避免Python中类似的函数定义?,python,function,Python,Function,我的Python代码中有一系列非常类似的函数,如下所示: def callback1(msg): m = MsgX(msg) a = msg_type_a() a.x = m.x pub2.publish(a) def callback2(msg): m = MsgY(msg) b = msg_type_b() b.t = m.t b.u = m.u pub2.publish(b) # ... and a couple
def callback1(msg):
m = MsgX(msg)
a = msg_type_a()
a.x = m.x
pub2.publish(a)
def callback2(msg):
m = MsgY(msg)
b = msg_type_b()
b.t = m.t
b.u = m.u
pub2.publish(b)
# ... and a couple more in the same fashion
有什么方法可以避免在不影响执行速度的情况下重复定义这些函数吗?听起来像是在类之后,它们允许您将方法和变量分配给其他结构相同的对象没有宏,但您可以创建一个定义另一个函数并返回它的函数:
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\u type\u a
一起),那么您可以在某个地方的字典中明确显示该信息,并使用该字典从一个或几个“键值”派生调用的各个部分。您不需要宏来实现这一点;函数是一级对象,可以动态构建:
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\u type
事物中的每一个都是namedtuple
-ish类型(具有\u字段
或\uu插槽
或某些其他属性名称的iterable):
或者,如果msg_类型
s只知道如何从msg类型
构造它们自己:
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)
或者,如果msg类型
知道如何将自己转换为msg_类型
(甚至可能是动态生成的类型):
等等。所有基本的OO设计在适当的时候都可以在Python中使用(很难从您的玩具示例中知道什么是适当的),但是当它们不合适时,您可以使用很多反射/动态特性
这会影响性能吗
好吧,你要么在一个包含两件事的列表上循环,要么添加一个额外的函数调用,这需要几纳秒的时间。但这真的很重要吗?如果是这样的话,你几乎肯定会想改变你的设计,这样就可以更便宜地构造
msg_类型
类型(例如,在一次调用中),等等,在这样做的同时,你可以加入一些东西,使这部分更容易优化。除了pub2.publish(a)
这些函数实际上并不完全相同。另外,a
甚至不是函数作用域中的变量?我假设第二个应该有pub2.publish(b)
@poke:有一个非常清晰的并行结构。它们有不同的MsgSpam
类型、不同的msg\u type\u spam
类型和不同的属性列表,但在其他方面它们做的事情是相同的。@abarnert当然我看到了结构,但很难说出这种函数的变量到底是什么(不过你的回答很好).我刚刚测试了执行速度。对于这个特殊的案例,没有明显的区别。@DanielEckert:Good;测试总是比猜测好。:)
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)
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)