代码之家  ›  专栏  ›  技术社区  ›  Jon Cage

为什么导入Python类会实例化它?复制

  •  1
  • Jon Cage  · 技术社区  · 1 年前

    这里有一个从一些永远不会退出的PyTest单元测试中截取的示例。如果我坚持一个断点 DataListener.__init__ 我看到它被呼叫 from controller import Controller 中的声明 test_controller.py 这让我有点吃惊;为什么从模块导入类会实例化它的实例?

    data_listener.py

    class DataListener:
    
        def __init__(self, port, host='localhost'):
            self._stop_monitor = Event()
            self._monitor = Thread(target=self.check_last_message)
            self._monitor.start()
    
        def __del__(self):
            self.stop()
    
        def stop(self):
            self._stop_monitor.set()
            self._monitor.join()
    
        def check_last_message(self):
            while not self._stop_monitor.is_set():
                # Code to check for a heartbeat here
                pass
    

    控制器.py

    from data_listener import DataListener
    
    class Controller:
        def __init__(
            self,
            subscriber=DataListener(port=DEFAULT_SUBSCRIBER_PORT),
            publisher=JsonPublisher(DEFAULT_PUBLISHER_PORT)):
    
            pass
    

    test_controller.py

    from controller import Controller
    
    def test_controller_work_loop():
        # ARRANGE
        controller = Controller(subscriber=None, publisher=None)
    
        # Some actual tests here
        # This test passes and finishes but the test suite never exits
    
    1 回复  |  直到 1 年前
        1
  •  4
  •   jonrsharpe    1 年前

    加载类时会计算默认参数。

    from data_listener import DataListener
    
    class Controller:
        def __init__(
            self,
            subscriber=DataListener(port=DEFAULT_SUBSCRIBER_PORT),  # These are run!
            publisher=JsonPublisher(DEFAULT_PUBLISHER_PORT)):
    
            pass
    

    你需要更新你的 Controller 类,以便在初始化器中惰性地初始化它们

    from data_listener import DataListener
    
    class Controller:
        def __init__(self, subscriber=None, publisher=None):
            self.subscriber = subscriber or DataListener(port=DEFAULT_SUBSCRIBER_PORT)
            self.publisher = publisher or JsonPublisher(DEFAULT_PUBLISHER_PORT)