python 关于类的__call__(self,...)的使用

本文探讨了Python类中的__call__方法。在没有__call__的情况下,类的实例不能直接作为函数调用。然而,通过实现__call__,我们可以使类的实例变得可调用,允许它们像函数一样被使用,从而重载了括号运算符。

一个没有__call__(self,…)的类,一个有__call__(self,…)的类

class Name(object):
	def __init__(self,name1,name2,name3):
		self._name1 = name1
		self._name2 = name2
		self._name3 = name3

	
你遇到的错误: ``` Unresolved reference 'loop' ``` 是因为你在 `BleCallbacks.on_scan_callback` 方法中使用了 `loop.call_soon_threadsafe(...)`,但 `loop` 并没有在该方法中定义,也没有通过参数传入。 --- ### 🔍 问题分析 你已经在 `BleAsyncClient` 中获取了 `loop = asyncio.get_running_loop()`,但这个 `loop` 变量并没有传给 `BleCallbacks` 。 所以你需要把 `loop` 传入 `BleCallbacks`,例如在初始化时传入: --- ### ✅ 修复方法:将 loop 传入 BleCallbacks ```python class BleCallbacks: def __init__(self, mgr: OperationManager, loop): self._mgr = mgr self._loop = loop def on_scan_callback(self, op_id: int, address, rssi, msg): self._loop.call_soon_threadsafe(self._mgr.resolve, op_id, (address, rssi, msg)) class BleAsyncClient: def __init__(self): self.loop = asyncio.get_running_loop() self._mgr = OperationManager() self._callbacks = BleCallbacks(self._mgr, self.loop) CALLBACK = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_uint64, ctypes.c_int, ctypes.c_wchar_p) self._scan_cb = CALLBACK(self._callbacks.on_scan_callback) # Register callback to DLL bledll.RegisterScanCallback(self._scan_cb) bledll.BLE_StartScanForAddress.argtypes = [ctypes.c_int, ctypes.c_uint64] bledll.BLE_StartScanForAddress.restype = None self._next_op_id = 1 def _next_id(self): val = self._next_op_id self._next_op_id += 1 return val ``` --- ### ✅ 补充说明 - `loop.call_soon_threadsafe()` 用于在异步线程安全的方式中调用协程函数; - 如果回调函数是由 C/C++ 的 DLL 在另一个线程中触发的(非事件循环线程),那么你**必须**使用 `call_soon_threadsafe`,否则会出错; - 你也可以考虑将 `loop` 作为参数传入回调函数,而不是保存在 `BleCallbacks` 中,但保存更方便复用。 --- ### ✅ 可选优化(将 loop 作为参数传入) 如果你不想把 loop 存在 `BleCallbacks` 中,也可以这样写: ```python def on_scan_callback(self, op_id: int, address, rssi, msg): loop = asyncio.get_event_loop() # 或 get_running_loop() loop.call_soon_threadsafe(self._mgr.resolve, op_id, (address, rssi, msg)) ``` 但注意: - `get_event_loop()` 在 Python 3.7+ 已不推荐; - 如果回调是在非主线程中调用的,建议使用 `get_event_loop()`; - 如果确保在事件循环线程中调用,可用 `get_running_loop()`。 --- ### ✅ 总结 | 问题 | 解决方法 | |------|----------| | `Unresolved reference 'loop'` | 将 loop 实例传入 BleCallbacks | | 回调是否在主线程中执行? | 如果是 DLL 触发,通常不是主线程,建议使用 `call_soon_threadsafe` | | 是否必须保存 loop? | 不是必须,但保存更方便;也可以每次获取 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值