python - 调味包

标签 python python-2.6

在与硬件通信时,我使用的包的结构有点类似于以下内容:

channel
   __init__.py
   transport
      __init__.py
      flow.py
      multiplex.py
   network
      __init__.py 
      header.py
      addressing.py 

我现在希望能够配置我的包,以便我可以使用它与两个非常相似的硬件进行通信。例如,当与 hw1 通信时,我希望在 adressing.py 中执行以下等效操作:

from collections import namedtuple
PacketSize = namedtuple('PacketSize', ('header', 'body'))
packet_size = PacketSize(16,256)

在测试 hw2 时,我想要相当于:

from collections import namedtuple
PacketSize = namedtuple('PacketSize', ('header', 'body'))
packet_size = PacketSize(8,256)

对于 hw1 和 hw2,软件包中的几乎所有模块都是相同的。然而,我什至可能对包中的某些函数和类有稍微不同的风格。

我想我可以通过这种结构来解决这个问题:

channel
   __init__.py
   transport
      __init__.py
      flow.py
      multiplex.py
   network
      __init__.py 
      header.py
      addressing.py
      hw1
         __init__.py 
         addressing.py
      hw2    
         __init__.py 
         addressing.py

因此每个子包将包含一个 hw1 和 hw2 子包,其中放置硬件特定代码。我对channel/network/addressing.py进行了如下编程:

from collections import namedtuple
PacketSize = namedtuple('PacketSize', ('header', 'body'))
if hardware == "hw1":
   from hw1.targetprops import * 
elif hardware == "hw2":
   from hw2.targetprops import * 

还有channel/network/hw1/addressing.py,如下所示:

from ..addressing import PacketSize
packet_size = PacketSize(16,256)

这有道理吗?老实说,我认为 channel/network/addressing.py 很难看,因为我正在执行导入,然后定义一个命名元组,然后继续条件导入。我可以做得更好吗?

上述一般方法是给包装调味的最佳方法吗?

是否有标准方法来配置包,以便它知道它是否与 hw1 或 hw2 相关?目前,当我执行 if harware == "hw1" 时,我只有一个名为 hardware 的全局硬件,如上所示。

最佳答案

您应该尝试抽象出某种通用接口(interface)背后的硬件/风格相关功能。有许多不同的方法可以做到这一点,例如类继承,composition ,传递一个对象,或者 --- 正如您可能想要做的那样 --- 甚至作为全局 python 模块或对象。

我个人倾向于倾向于组合,因为类继承通常并不自然,并且可能会导致多重继承或MixInMadness

全局 Python 模块(或 sigleton 对象)很有吸引力,但我会避开,除非在单个进程中真的、真的必须只有其中一个。很好的设计例子是当它与底层平台绑定(bind)时,例如 Python os 模块,它在 Windows 和 Linux 上具有大致相同的界面,但在底层的工作方式却截然不同。将此与您的 hw1hw2 进行比较。另一个很好的例子是 Twisted react 堆,它一次只能运行一个。即使这样,Twisted 代码的很大一部分也会传递一个 Reactor 对象以进行合成等操作。这在一定程度上是为了使单元测试成为可能。

对于您的示例,如果 hw1 或 hw2 指的是您的程序正在运行的硬件,那么全局 python 模块确实有意义。如果它指的是程序正在与之通信的硬件,例如通过串行端口或网络,那么全局模块是错误的方法。您可能有两个串行端口,并希望在同一进程中与 hw1 和 hw2 通信。

有关如何使用全局模块或实际上是全局对象的示例,我建议查看 how Twisted does it 。然后你的模块会做类似的事情

from mypackage import hardware # hw1/hw2 automatically detected

print hardware.packet_size # different for different hardware

# main.py
from mypackage import hw1
hw1.init()

# other.py
from mypackage import hardware # initialized to hw1 in main.py

另一方面,合成或传递对象看起来像:

hw = mypackage.hw1.hw1factory()
send_data(hw, 'foo') # uses hw.packet_size

hw = mypackage.hw2.hw2factory()
frob = Frobnicator(hw)
frob.frobnicate('foo') # uses hw.packet_size internally

关于python - 调味包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25936236/

相关文章:

Python如何获取实例的基础实例?

python - python中的check_output错误

python-2.6 - 在全局包上导入本地包

python - pymunk中自上而下的摩擦力

Python:从函数返回数组值

python - Python 2.6 与 2.7 中的浮点行为

python - 如何在不按回车键的情况下在 python 中获取按下的键?

python - 用于启动 test_train_split 的数组切片符号?

python - 来自 Google 新闻的网络抓取文章

python - 如何对数据框进行线性回归?