【问题标题】:Class hierarchy in PythonPython中的类层次结构
【发布时间】:2017-11-01 18:08:35
【问题描述】:

我有一个使用 Python 绑定通过 Firmata 协议连接到 arduino 的中继板。使用 pyfirmata (https://github.com/tino/pyFirmata) 进行通信没有问题。

relaisboard 有 16 个 relais。每组 3 个继电器为一个通道。每个通道都连接到被测设备的输入或输出。这只是为了粗略描述一下releboard的目的。

您可以在下面找到代码的骨架。

#!/usr/bin/env python

__version__ = '0.1'

# Fault Injection Unit

# Power is connected to Fault Bus 1
# Ground is connected to Fault Bus 2

from pyfirmata import Arduino

class FaultInsertionBoard(object):

    def __init__ (self, comPort = 'COM3'):
        """Initalize the Fault insertion Board

        Open communication with host via serial port

        Arguments:
        comPort -- The serial port used to connect the board to the host.
        """
        self.board = Arduino(comPort)

    class Channel(object):

        def __init__ (self, aChannel):
            """ Create a Channel"""
            pass

        def NoFault():
            """ Set the channel to the "No fault" condition

            No Fault condition is:
            -- DUT channel connected to the testing sistem
            -- DUT channel disconnected from the Fault bus 1  
            -- DUT channel disconnected from the Fault bus 2
            """
            pass


        def OpenCircuit():
            """ Set the channel to the "Open Circuit fault" condition

            Open Circuit fault condition is:
            -- DUT channel disconnected from the testing sistem
            -- DUT channel disconnected from the Fault bus 1  
            -- DUT channel disconnected from the Fault bus 2
            """
            pass

        def ShortToGround():
            """ Set the channel to the "Short to Ground fault" condition

            Open Circuit fault condition is:
            -- DUT channel disconnected from the testing sistem
            -- DUT channel disconnected from the Fault bus 1  
            -- DUT channel connected to the Fault bus 2
            """
            pass

        def ShortToPower():
            """ Set the channel to the "Short to Ground fault" condition

            Open Circuit fault condition is:
            -- DUT channel disconnected from the testing sistem: channel relay is open
            -- DUT channel connected to the Fault bus 1: Fault Bus 1 relay is closed 
            -- DUT channel disconnected from the Fault bus 2: Fault Bus 1 relay is open
            """
            pass

def main():

    FaultBoard = FaultInsertionBoard('COM3')
    VoutSensor = FaultBoard.Channel(0)  
    IOutSensor = FaultBoard.Channel(1)    
    VoutSensor.NoFault()
    IOutSensor.NoFault()
    VoutSensor.ShortToGround()
    IOutSensor.ShortToPower()

if __name__ == "__main__":
    main()

地点:

  • FaultInsertionBoardArduino 类的简单包装器 Firmata
  • Channel(n) 标识n-th 组三个继电器
  • NoFaultShortToPowerShortToGround是各种配置 每个通道的三个继电器(与实际无关) 配置)。

现在的问题是:我对用 C 编写的嵌入式固件有很好的体验,而用 Python 编写的固件要少得多。显然上面的代码是不正确的。

有人可以建议我一个类框架来获得上述功能吗?换句话说,如何编写 Python 代码来驱动上述继电器?

PS:或者我可以这样写:

FaultBoard = FaultInsertionBoard('COM3')
FaultBoard.Channel(0).NoFault()

但我认为它不那么优雅和清晰。

【问题讨论】:

  • 你没有显示FaultInsertionBoard的代码;您希望如何获得帮助?
  • 你贴的代码是不是不能用?
  • 对不起,我的错。我以为我放了代码。请参阅上面我编辑的问题。
  • 不要定义嵌套类。它在 Python 中毫无用处。如果这只是一个缩进错误,请修复它。
  • 所以您要求我们为您实现您的课程?

标签: python class-hierarchy


【解决方案1】:

一方面,您的实际问题很笼统,以后您应该尝试更具体一些。另一方面,初学者通常很难知道从哪里开始,因此我将为您提供一些设计技巧,帮助您度过这一挑战。

没有嵌套类

嵌套类在 Python 中几乎没有用处。完全合法,但毫无意义。它们不会让您神奇地访问包含的类,并且不会出现在任何实例中(就像它们在 Java 中一样)。嵌套所做的只是使命名空间更加复杂。

我要做的第一件事是将Channel 移出FaultInsertionBoard。一个简单的取消缩进就足够了。下面我会告诉你如何使用它。

命名约定

要记住的另一件事是 Python 命名约定。虽然不是必需的,但通常只大写类名,而其他所有内容都是小写,单词之间有下划线(而不是 camelCase)。

在定义函数参数的默认值时,在 = 周围放置空格也是常规的

我将在整个答案中遵循这些约定。

继承与遏制

对于FaultInsertionBoard,您可能应该使用继承而不是包含:

class FaultInsertionBoard(Arduino):
    pass

这将使FaultInsertionBoard 拥有Arduino 的所有方法和属性。您现在可以使用fault_board.method() 而不是fault_board.board.method(),其中methodArduino 类的一些方法。

您可能需要定义一些额外的初始化步骤,例如为com_port 设置默认值,然后设置通道。您可以定义自己的__init__ 版本,并随时调用父类的实现:

class FaultInsertionBoard(Arduino):
    def __init__(self, com_port='COM3'):
        super().__init__(com_port)

如果您使用 Python 2.x,请使用 super(FaultInsertionBoard, self).__init__

添加频道

为了能够实际访问通道实例,您需要定义一些数据结构来保存它们,并预先初始化一些通道。数据结构可以作为属性直接访问,也可以通过对参数进行一些额外检查的方法访问。

正如我之前提到的,嵌套Channel 类根本不会让您朝这个方向发展。实际上,由于您的Channel 类可能需要访问其父板,因此我们将为其构造函数添加一个新的初始化参数:

class Channel:
    def __init__(self, channel_id, parent):
        self.id = channel_id
        self.parent = parent

您有多种选择。最简单的就是在FaultInsertionBoard中初始化一系列Channels,可以通过[]而不是()访问:

class FaultInsertionBoard(Arduino):
    def __init__(self, com_port='COM3'):
        super().__init__(com_port)
        self.channels = []
        self.channels.append(Channel(0, self))
        self.channels.append(Channel(1, self))
        ...

现在main 将如下所示:

def main():
    fault_board = FaultInsertionBoard('COM3')
    v_out_sensor = fault_board.channels[0]  
    i_out_sensor = fault_board.channel[1]
    v_out_sensor.no_fault()
    v_out_sensor.short_to_ground()
    i_out_sensor.no_fault()
    i_out_sensor.short_to_ground()

如果你绝对想用括号来访问channel(0)等的频道,你可以在FaultInsertionBoard中定义一个方法。保持__init__方法不变,你可以添加另一个方法:

def channel(self, index):
    # Check index if you want to, possibly raise an error if invalid
    return self.channels[index]

在这种情况下,main 将如下所示:

def main():
    fault_board = FaultInsertionBoard('COM3')
    v_out_sensor = fault_board.channel(0)  
    i_out_sensor = fault_board.channel(1)
    v_out_sensor.no_fault()
    v_out_sensor.short_to_ground()
    i_out_sensor.no_fault()
    i_out_sensor.short_to_ground()

第一种方法的优点是允许您直接访问Channel 对象的序列。由于您对通道应用相同的操作,因此您可以遍历所有通道以获得更简单的界面:

def main():
    fault_board = FaultInsertionBoard('COM3')
    for channel in fault_board.channels:
        channel.no_fault()
        channel.short_to_ground()

便捷方法

您的代码中似乎多次使用了操作x.no_fault(); x.short_to_ground()。在这种情况下,创建所谓的便捷方法通常很有帮助。您可以将以下内容添加到Channel

def reset(self):
    self.no_fault()
    self.short_to_ground()

然后main 可能看起来像这样:

def main():
    fault_board = FaultInsertionBoard('COM3')
    for channel in fault_board.channels:
        channel.reset()

【讨论】:

    猜你喜欢
    • 2011-01-18
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 2011-05-19
    相关资源
    最近更新 更多