听起来您有list
10 个项目,然后您想在 中的每个项目上运行 50 个函数list
,并且您不想编写 50 个for
循环。
一种可能性是编写一个将其包装起来的函数:
def apply(method, seq):
for item in seq:
method(item)
然后,而不是这个:
for thing in self.list_of_objects: # Yuck!!
thing.some_function()
for thing in self.list_of_objects: # Yuck!!
thing.other_function()
for thing in self.list_of_objects: # Yuck!!
thing.third_function()
# ... 47 more times
你可以这样做:
apply(ThingClass.some_function, self.list_of_objects)
apply(ThingClass.other_function, self.list_of_objects)
apply(ThingClass.third_function, self.list_of_objects)
# ... 47 more times
函数和方法是 Python 中的一等对象,就像其他任何东西一样,因此您可以轻松地将它们传递给其他函数。当然first_thing.some_function
和second_thing.some_function
实际上是不同的绑定方法;诀窍是您可以从类中获取未绑定的方法,然后将对象作为显式self
参数传递给它。(尝试打印出first_thing.some_function
、ThingClass.some_function
、type(first_thing.some_function)
和type(ThingClass.some_function)
,并在交互式解释器中使用它们。)
当然,这假设所有这些项目具有相同方法的原因是它们是同一类的实例。如果这不是真的,并且您依赖于鸭子打字,那么您需要一些稍微不同的东西:
def apply(methodname, seq):
for item in seq:
getattr(item, methodname)()
apply('some_function', self.list_of_objects)
# ... 49 more times
在这里,诀窍是getattr
函数,它允许您在运行时按名称获取任何方法或成员。
但是如果你仔细想想,你真正想要的是迭代这 50 个未绑定的方法或名称,而根本不必重复自己。例如:
for name in ('some_function', 'other_function', 'third_function',
# ... 47 more names
):
for obj in self.list_of_objects:
getattr(obj, name)()
请注意,该apply
方法的第一个版本可以很容易地被内置的map
(仅在 Python 2.x,而不是 3.x 中),甚至是列表推导式替换。但是,有一些理由不这样做:
map
当您仅调用该函数的副作用时,它通常被认为是有问题的使用风格或理解。
- 如果您有很多项目,而不仅仅是 50*10,那么它会浪费内存和时间来构建
list
您不需要的结果。
- 在 Python 3 中,
map
返回一个迭代器而不是 a list
,因此它实际上根本不会执行函数,除非您以某种方式对其进行迭代。(由于您的print
陈述,您今天显然在使用 2.x,但大概有一天您会切换到 3.x。)
itertools.imap
您可以通过使用(或生成器表达式)而不是map
(或列表推导式)并通过例如将其馈入 0-sized 来处理可迭代对象来解决这些问题deque
。但到那时,您的代码在做什么并不完全清楚。
同时,显式编写函数意味着当您发现需要时很容易修改为例如第二个版本。