在内部类变量分配内访问类变量

时间:2018-07-04 13:04:53

标签: python python-3.x

我想使用一个类变量作为同一类中另一个变量的定义的一部分,如下所示:

import enum, struct

class Message:
    """ExtendedIO related message IDs and `Struct.struct`s."""

    # protocol
    BYTE_ORDER = "<"

    # Message ID's
    class ID(enum.IntEnum):
        """Message ID's definitions."""
        EX_IO = 0x01
        ALIVE = 0x02
        RESETCOMPONENT = 0x03

    STRUCTS = {
        ID[message_id]: struct.Struct(
            ''.join((BYTE_ORDER, format)))
        for message_id, format in {
            'EX_IO': "B",          # command
            'ALIVE': "HH",         # version, version
            'RESETCOMPONENT': ""}  #
        .items()}

这给出一个NameError: name 'BYTE_ORDER' is not defined

我可以做到:

import enum, struct

class Message:
    """ExtendedIO related message IDs and `Struct.struct`s."""

    # protocol
    BYTE_ORDER = "<"

    # Message ID's
    class ID(enum.IntEnum):
        """Message ID's definitions."""
        EX_IO = 0x01
        ALIVE = 0x02
        RESETCOMPONENT = 0x03

class Message(Message):

    STRUCTS = {
        Message.ID[message_id]: struct.Struct(
            ''.join((Message.BYTE_ORDER, format)))
        for message_id, format in {
            'EX_IO': "B",          # command, *
            'ALIVE': "HH",         # version, version
            'RESETCOMPONENT': ""}  #
        .items()}

它确实有效,但是多余的class Message(Message):看起来很丑,而且pylint抱怨E0102

分配Message.STRUCT的好处是它使用了非常易读的表。 (我正在处理的实际代码要复杂一些。)

根据评论,我尝试了以下代码,该代码有效:

import enum, struct

class Message:
    """ExtendedIO related LWF message IDs and `Struct.struct`s."""

    # protocol
    BYTE_ORDER = "<"

    # Message ID's
    class ID(enum.IntEnum):
        """Message ID's definitions."""
        EX_IO = 0x01
        ALIVE = 0x02
        RESETCOMPONENT = 0x03

    EXAMPLE = ''.join((BYTE_ORDER, '1'))

    STRUCTS = lambda ID, BYTE_ORDER: {
        ID[message_id]: struct.Struct(
            ''.join((BYTE_ORDER, format)))
        for message_id, format in {
            'EX_IO': "B",          # command
            'ALIVE': "HH",         # version, version
            'RESETCOMPONENT': ""}  #
        .items()}(ID, BYTE_ORDER)

所以:

  • 直接使用类变量即可。
  • 使用lambda将变量插入到理解中也可以。
  • 使用额外的class Message(Message):可以正常工作。 (并且importlib.reload()适用于第一个代码示例,但是结果是错误的...)

在Python中同一类的另一个类变量中是否有使用类变量的明智方法?

2 个答案:

答案 0 :(得分:0)

根据使用变量 class 而不是 instance 变量的方式,您还可以在构造函数中更改现有的类变量。这样,您的变量仍然是该类的所有实例共享的类变量。

class Message:
    BYTE_ORDER = "<"
    STRUCTS = {}

    def __init__(self):
        STRUCTS = self.SomethingDependantOn(self.BYTE_ORDER)    

但是,如果不先实例化对象,就无法访​​问变量。

答案 1 :(得分:0)

您可以使用 self

访问此变量
class Message:
    """ExtendedIO related message IDs and `Struct.struct`s."""

    # protocol
    BYTE_ORDER = "<"

    # Message ID's
    class ID(self, enum.IntEnum):
        """Message ID's definitions."""
        EX_IO = 0x01
        ALIVE = 0x02
        RESETCOMPONENT = 0x03

    def something(self):
        STRUCTS = {
            ID[message_id]: struct.Struct(
                ''.join((self.BYTE_ORDER, format)))
            for message_id, format in {
                'EX_IO': "B",          # command
                'ALIVE': "HH",         # version, version
                'RESETCOMPONENT': ""}  #
            .items()}

或仅设置变量全局变量并按您的班级进行访问

# protocol
BYTE_ORDER = "<"

class foo():
    def something():
        print(BYTE_ORDER)

class bar():
     def something():
        print(BYTE_ORDER)