我有一个从不同类实例化的对象列表。我想在该列表中的某个类的所有对象上调用某个方法。我觉得我找到的方式并不是很优雅,而且可能会有更好的方式。
目前,我这样做:
def execute(fn, classname, objlist):
'''
The function that iterates over all objects,
finds the fitting ones, and executes the chosen "fn"
'''
for obj in objlist:
# Checks for the class from which the object was instantiated
if type(obj) is classname:
# Execute the function.
fn(obj)
class C():
def myfn(self):
print("foo")
class D():
def otherfn(self):
print("bar")
objlist = []
objlist.append(C())
objlist.append(D())
execute(C.myfn, C, objlist)
execute(D.otherfn, D, objlist)
输出是:
foo
bar
有更好的方法吗?
编辑:澄清问题
我会尝试以简单的方式说明问题,我希望我不会用细节来压倒你。
我的应用程序与我网络上的以太网连接的嵌入式工作站连接。每个站由不同的类表示,每个类提供不同的功能来控制该站。
首先,必须执行扫描,以便我知道哪些站点实际上在网络上可用。因此,一个基本的"站"对象被创建并且"扫描"叫做。扫描是期望来自电台的答复的请求。如果有答案,它将指定所连接电台的确切类型。
其次,基站需要通过"模式扩展"这是刚刚通过第一次扫描步骤发现的。 "基本"模式由电台所在的特定模式取代。"基本"模式只允许刚执行的扫描。
这是实际的基站类。 __LinkUI包含有关输入用户界面的内容的一些信息,如IP地址范围和端口:
class Station(__LinkUI):
'''
Generic class for creating a station. This is used first for
stations that have no known type yet
'''
def __init__(self, ip, storage):
super().__init__(storage)
# IP Address of this station
self.ip = ip
# The handling object for the TCP connection to this station
self.handler = Handler(self.storage.network.confport, self.pool)
# Last response value to a request message
self.response = None
# mode of this station. This is an object that details
# some functions and variables for controlling a certain
# type of station. "Basic" is the default mode with
# no special functions
self.mode = Basic(self)
# Hardware architecture of a station, like DDS/PLL
self.architecture = None
这是"模式的一个例子" class,like" Boot",表示处于引导加载程序模式的工作站。这种"模式"扩展了" Station"的功能。对象
class Boot(__Mode):
'''
Extends a station by the boot mode
'''
def __init__(self, station):
self.name = "Boot"
super().__init__(self, station)
# The interface for using the flash mode of the boot station
self.flashInterface = FlashInterface(station)
self.healthInterface = HealthInterface(station)
def flash(self, callback, data):
self.flashInterface.flash(callback, data)
def run(self, callback):
self.flashInterface.run(callback)
__ Mode是连接一些变量并生成" Messenger"的基类。用于生成发送到工作站的实际原始消息:
class __Mode():
'''
Base class for different station modes (Boot, Rx, Tx, Central)
'''
def __init__(self, child, station):
# Generate a messenger object for this kind of station
self.messenger = GetMessenger(child)
# Connect variables
self.station = station
station.mode = child
station.name = child.name
station.messenger = child.messenger
我做了所谓的"接口"附加到" Mode"对象并提供以某种方式控制电台的功能。我可以将多个接口连接到一个站,因此它可以获得所有接口的功能。
总之,电台可能非常不同,我不确定多态是否适用。方法名称,功能或参数不同。
抱歉,如果缺少信息或提供太多信息。
答案 0 :(得分:0)
一种解决方案是在基类Mode
类中实现所有可能的操作(作为无操作),这样您就可以调用任何操作而无需担心对象的当前模式。
另一种解决方案是使用getattr()
和方法名称:
def execute(objlist, methodname, *args, **kw):
for obj in objlist:
method = getattr(obj, methodname, None)
if method:
method(*args, **kw)
FWIW,你在Mode
课程中所拥有的实际上是一个不完整的“状态”模式。 You may want to read about it...
答案 1 :(得分:0)
恕我直言你的测试,以了解一个对象属于一个类是否过于严格,并没有正确处理子类型。例如,我将它添加到您的代码中:
class E(C):
pass
objlist.append(E())
objlist
现在包含一个C实例,一个D和一个E.但是E实例也是C继承,所以我希望输出:
execute(C.myfn, C, objlist)
是:
foo
foo
所以我会重写你的功能:
def execute(fn, classname, objlist):
'''
The function that iterates over all objects,
finds the fitting ones, and executes the chosen "fn"
'''
for obj in objlist:
# Checks for the class from which the object was instantiated
if isinstance(obj, classname):
# Execute the function.
fn(obj)