简体   繁体   English

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

[英]Accessing a class variable within inner class variable assignment

I would like to use a class variable as part of the definition of another one within the same class as follows: 我想使用一个类变量作为同一类中另一个变量的定义的一部分,如下所示:

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()}

This gives a NameError: name 'BYTE_ORDER' is not defined . 这给出了NameError: name 'BYTE_ORDER' is not defined

I can do: 我可以:

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()}

And it works, but the extra class Message(Message): looks ugly and pylint complains with an E0102 . 它可以工作,但是额外的class Message(Message):看起来很丑,而pylint抱怨E0102

The benefit of the way Message.STRUCT is assigned is that it uses a very readable table. 分配Message.STRUCT的好处是它使用了一个非常易读的表。 (The actual code I am working on is a bit more complex.) (我正在处理的实际代码要复杂一些。)

Based on the comments, I tried the following code, which works: 根据评论,我尝试了以下代码,该代码有效:

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)

So: 所以:

  • Directly using a class variable works. 直接使用类变量即可。
  • Inserting the variables into the comprehension using a lambda also works. 使用lambda将变量插入到理解中也可以。
  • Using the extra class Message(Message): works. 使用额外的class Message(Message):有效。 (and importlib.reload() works on the first code example, but the result is wrong...) (并且importlib.reload()适用于第一个代码示例,但是结果是错误的...)

Is there a sane way of using a class variable within another class variable in the same class in Python? 在Python中同一类的另一个类变量中是否有使用类变量的明智方法?

Depending on the way you make use of the variables being class instead of instance variables, you could also change an existing class variable in your constructor. 根据使用变量而不是实例变量的方式,还可以在构造函数中更改现有的类变量。 This way, your variable is still a class variable shared by all instances of the class. 这样,您的变量仍然是该类的所有实例共享的类变量。

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

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

You would not be able to access the variable without instantiating an object first though. 但是,如果不首先实例化对象,就无法访​​问变量。

You can access this variable using self 您可以使用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()}

or just set your varible global and access it by your classes 或只是设置您的变量全局变量并按您的班级进行访问

# protocol
BYTE_ORDER = "<"

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM