从python工厂中导入
我想创建一个抽象工厂,以便在Python2.7中抽象计算机(比如RaspberryPi和Arduino)之间的硬件差异 我正在使用抽象工厂的以下实现:从python工厂中导入,python,abstract-factory,new-style-class,Python,Abstract Factory,New Style Class,我想创建一个抽象工厂,以便在Python2.7中抽象计算机(比如RaspberryPi和Arduino)之间的硬件差异 我正在使用抽象工厂的以下实现: ''' Provide a device-agnostic display interface ''' from hardware import sysname class DisplayBase(object): def __init__(self): pass de
'''
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
…这会在RPI上失败,这很好,但一定有更好的方法…您是否尝试过使用arduino的导入println
然后像使用RPIwriteline一样使用println
编辑:忽略了明显的
你可以这样做:
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")
如果您需要类和嵌套工厂,也可以应用同样的原则将函数对象存储在那里。问题是,您导入的函数没有保存在任何地方,其他方法无法看到它们,因此它们除了在本地之外,在其他任何地方都不可见。导入后,请尝试设置ArduinoDisplay.arduino\u display=arduino\u 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")
此操作失败,原因是名称错误:未定义名称“display\u write”
现在,将导入绑定到类
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")
问题是由于import
仅在其当前作用域中绑定名称。在函数/方法中执行导入
,不会使其在其他方法中可用
在实际需要的地方执行导入。例如,ArduinoDisplay
应在使用它的地方导入arduino\u 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
有一个输入错误:ArduionDisplay在其中的某个位置。您是否尝试将导入设置为全局?修复了该输入错误。问题是,您的导入没有保存在任何位置,其他方法无法看到它们,因此它们除了本地之外在其他任何位置都不可见。导入后,请尝试设置ArduinoDisplay.arduino\u display=arduino\u display
。您可能需要使用staticmethod,如ArduinoDisplay.arduino\u display=staticmethod(arduino\u display)
中所示。现在,在show
中使用ArduinoDisplay.arduinou display
,即保存的导入。
# ## 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