为了账号安全,请及时绑定邮箱和手机立即绑定

从 python 抽象工厂中导入

从 python 抽象工厂中导入

慕田峪9158850 2022-07-12 17:56:49
我想创建一个抽象工厂,以便在 Python 2.7 中抽象计算机(比如 RaspberryPi 和 Arduino)之间的硬件差异。我正在使用抽象工厂的以下实现:  '''  Provide a device-agnostic display interface  '''  from hardware import sysname  class DisplayBase(object):        def __init__(self):           pass        def show(self, message):           pass        def __str__(self):           return "DisplayBase"        def __repr__(self):           return self.__str__()   class RPIDisplay(DisplayBase):        def __new__(cls, *args, **kwargs):            from rpi_display import writeline            instance = super(RPIDisplay, cls).__new__(cls, *args, **kwargs)            return instance        def __str__(self):            return "RPIDisplay"       def show(self, message):           writeline(message)    class ArduinoDisplay(DisplayBase):        def __new__(cls, *args, **kwargs):            import arduino_display            instance = super(ArduinoDisplay, cls).__new__(cls, *args, **kwargs)            return instance        def __str__(self):            return "ArduinoDisplay"        def show(self, message):            return arduino_display.println(message)   class Display(DisplayBase): # Display Factory       def __new__(cls, *args, **kwargs):           platform = sysname()           if platform == "RaspberryPi":               return RPIDisplay()           elif platform == "Arduino":               return ArduinoDisplay()           else:               return MockDisplay()    if __name__ == "__main__":        display = Display()        print display        display.show("hello world")实例化工作正常,但是当我尝试运行它时,我得到:    ArduinoDisplay    Traceback (most recent call last):    File "tt.py", line 56, in <module>      display.show("hello world")    File "tt.py", line 41, in show      return arduino_display.println(message)    NameError: global name 'arduino_display' is not defined所以导入arduino_display确实有效,但我找不到在对象中使用它的方法。需要条件导入,因为不同的平台将安装不同的模块。知道如何使用这些条件导入吗?我尝试过self.arduino_display,ArduinoDisplay.arduino_display但无济于事。
查看完整描述

3 回答

?
慕容3067478

TA贡献1773条经验 获得超3个赞

问题是由于仅在其当前范围内import绑定名称。在函数/方法中执行操作不会使其在其他方法中可用。import


在您实际需要的地方执行导入。例如,ArduinoDisplay应该在使用它的地方导入arduino_display:


class ArduinoDisplay(DisplayBase):

    # no new, no import


    def __str__(self):

        return "ArduinoDisplay"


    def show(self, message):

        # import where needed

        import arduino_display

        return arduino_display.println(message)

请注意,这import是幂等的——如果模块之前已经加载过,import只需再次绑定名称即可。这使得这种嵌套import语句对于大多数情况来说足够快。


如果您的类需要多次导入或速度存在问题,请将类隔离到单独的模块中并有条件地导入整个模块。您可以使用通用名称直接分配正确的类,而不是使用构造另一个的虚拟类型。


# ## display/arduino.py ##

# other systems accordingly

from .base import DisplayBase


# import once, globally

import arduino_display


class ArduinoDisplay(DisplayBase):

    # no new, no import


    def __str__(self):

        return "ArduinoDisplay"


    def show(self, message):

        # import where needed

        return arduino_display.println(message)


# ## display/__init__.py ##

from hardware import sysname


platform = sysname()

# resolve and import appropriate type once

if platform == "RaspberryPi":

    from .rpi import RPIDisplay as Display

elif platform == "Arduino":

    from .arduino import ArduinoDisplay as Display

else:

    from .mock import MockDisplay as Display


查看完整回答
反对 回复 2022-07-12
?
交互式爱情

TA贡献1712条经验 获得超3个赞

错过了明显的......


你可以这样做:


from hardware import sysname


class Display(object):

    def __init__(self, print_function, display_name):

        self._print_function = print_function

        self._display_name = display_name


    def show(self, message):

        self.print_function(message)


    def __str__(self):

        return self._display_name


    def __repr__(self):

        return self.__str__()


def create_display():

    platform = sysname()

    if platform == "RaspberryPi":

        from rpi_display import writeline

        return Display(writeline, "RPIDisplay")

    elif platform == "Arduino":

        from arduino_display import println

        return Display(println, "ArduinoDisplay")


如果您需要类和嵌套工厂,您也可以应用相同的原则将函数对象存储在那里。


查看完整回答
反对 回复 2022-07-12
?
catspeake

TA贡献1111条经验 获得超0个赞

问题是您导入的函数没有保存在任何地方以供其他方法查看,因此它们在其他任何地方都不可见,只能在本地看到。ArduinoDisplay.arduino_display = arduino_display导入后尝试设置。


这是一些示例代码,可以说明我的意思:


class ADisplay:


    def __init__(self):

        from builtins import print as display_write


    def show(self, msg):

        display_write(msg)


disp = ADisplay()

disp.show("mymsg")

这失败了NameError: name 'display_write' is not defined。


现在,将导入绑定到您的类。


class ADisplay:


    def __init__(self):

        from builtins import print as display_write

        ADisplay.display_write = display_write


    def show(self, msg):

        self.display_write(msg)


disp = ADisplay()

disp.show("mymsg")

这行得通。事实上show,如果所有这些硬件打印方法仅将字符串作为参数并且您不需要格式化或修改任何内容,您甚至可以通过直接分配来省去它。


class ADisplay:


    def __init__(self):

        #do other init stuff...

        pass


        #only bind show the first time.

        if getattr(ADisplay, "show", None):

            return


        from builtins import print as display_write

        ADisplay.show = display_write


disp = ADisplay()

disp.show("mymsg")


查看完整回答
反对 回复 2022-07-12
  • 3 回答
  • 0 关注
  • 143 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信