在 Python 中,创建一个包含多个对象的 list 很常见。例如,对于一组具有相同功能的对象(比如播放声音),希望能够使用类似
my_list.play()
的语法来触发 list 中所有对象的
play()
方法。另一个例子是,当希望关闭 list 中的所有对象时,可以使用类似
my_list.close()
的语法来触发 list 中所有对象的
close()
方法。
2. 解决方案
方法一:子类化 list
一种解决方案是子类化 list 并为子类添加所需的自定义方法。例如:
class ListContainer(list):
def play(self, *args, **kwargs):
for item in self:
item.play(*args, **kwargs)
def close(self, *args, **kwargs):
for item in self:
item.close(*args, **kwargs)
然后,可以像这样使用这个子类:
class Sound(object):
def __init__(self, name):
self.name = name
def play(self):
print(f'Playing {self.name}')
def close(self):
print(f'Closing {self.name}')
container = ListContainer([Sound('a'), Sound('b'), Sound('c')])
container.play()
container.close()
输出:
Playing a
Playing b
Playing c
Closing a
Closing b
Closing c
方法二:使用 map()
另一种解决方案是使用
map()
函数。
map()
函数可以将一个函数应用到一个可迭代对象中的每个元素上。例如:
def play(item):
item.play()
map(play, my_list)
这将对
my_list
中的每个元素调用
play()
方法。
方法三:显式迭代
有些情况下,显式地迭代 list 中的元素并调用它们的方法更为合适。例如:
for item in my_list:
item.play()
这将对
my_list
中的每个元素调用
play()
方法。
方法四:使用自定义类
如果需要对 list 进行更复杂的抽象,可以创建一个自定义类来实现所需的抽象。例如:
class MyList:
def __init__(self, *args):
self._list = list(args)
def __getattr__(self, name):
for item in self._list:
if hasattr(item, name):
return getattr(item, name)
raise AttributeError(f'{self.__class__.__name__} object has no attribute {name}')
def __setattr__(self, name, value):
for item in self._list:
if hasattr(item, name):
setattr(item, name, value)
else:
raise AttributeError(f'{item.__class__.__name__} object has no attribute {name}')
然后,可以像这样使用这个类:
class Sound(object):
def __init__(self, name):
self.name = name
def play(self):
print(f'Playing {self.name}')
def close(self):
print(f'Closing {self.name}')
my_list = MyList(Sound('a'), Sound('b'), Sound('c'))
my_list.play()
my_list.close()
输出:
Playing a
Playing b
Playing c
Closing a
Closing b
Closing c
哪种方法最适合取决于具体的情况。如果需要对 list 进行简单的抽象,可以使用子类化 list、
map()
函数或显式迭代的方法。如果需要对 list 进行更复杂的抽象,可以使用自定义类的方法。