Вернуть все значения переменных класса из класса Python

У меня есть класс Python, который содержит все регионы AWS. Я написал метод класса, который вернул бы мне список всех регионов. Есть ли лучший способ вернуть все значения переменных класса, чтобы мне не приходилось жестко кодировать все значения в операторе return, как я делаю в примере ниже?

class AwsRegion():
    '''
    Class to define AWS Regions
    '''
    OHIO = 'us-east-2'
    NORTH_VIRGINIA = 'us-east-1'
    NORTH_CALIFORNIA = 'us-west-1'
    OREGON = 'us-west-2'
    MUMBAI = 'ap-south-1'
    SEOUL = 'ap-northeast-2'
    SINGAPORE = 'ap-southeast-1'
    SYDNEY = 'ap-southeast-2'
    TOKYO = 'ap-northeast-1'
    FRANKFURT = 'eu-central-1'
    IRELAND = 'eu-west-1'
    LONDON = 'eu-west-2'
    SAO_PAULO = 'sa-east-1'

    @classmethod
    def all(cls, ):
        return [AwsRegion.OHIO, AwsRegion.NORTH_VIRGINIA, AwsRegion.NORTH_CALIFORNIA, AwsRegion.OREGON, \
            AwsRegion.MUMBAI, AwsRegion.SEOUL, AwsRegion.SINGAPORE, AwsRegion.SYDNEY, AwsRegion.TOKYO, \
            AwsRegion.FRANKFURT, AwsRegion.IRELAND, AwsRegion.LONDON, AwsRegion.SAO_PAULO]

person Varun Verma    schedule 27.06.2017    source источник
comment
all является атрибутом класса тоже. Вы имеете в виду что-нибудь, что не является вызываемым или иным образом дескриптором?   -  person Martijn Pieters    schedule 28.06.2017
comment
Должен быть более простой способ вернуть эти значения, чем их жесткое кодирование в списке...   -  person cs95    schedule 28.06.2017


Ответы (3)


В этом случае вы можете перечислить все атрибуты класса в верхнем регистре; Я бы использовал функцию vars() для доступа к пространству имен класса:

@classmethod
def all(cls):
    return [value for name, value in vars(cls).items() if name.isupper()]

Демо:

>>> class AwsRegion():
...     '''
...     Class to define AWS Regions
...     '''
...     OHIO = 'us-east-2'
...     NORTH_VIRGINIA = 'us-east-1'
...     NORTH_CALIFORNIA = 'us-west-1'
...     OREGON = 'us-west-2'
...     MUMBAI = 'ap-south-1'
...     SEOUL = 'ap-northeast-2'
...     SINGAPORE = 'ap-southeast-1'
...     SYDNEY = 'ap-southeast-2'
...     TOKYO = 'ap-northeast-1'
...     FRANKFURT = 'eu-central-1'
...     IRELAND = 'eu-west-1'
...     LONDON = 'eu-west-2'
...     SAO_PAULO = 'sa-east-1'
...     @classmethod
...     def all(cls):
...         return [value for name, value in vars(cls).items() if name.isupper()]
...
>>> AwsRegion.all()
['us-east-2', 'us-east-1', 'us-west-1', 'us-west-2', 'ap-south-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'sa-east-1']
person Martijn Pieters    schedule 27.06.2017

В качестве общей справки, вы можете получить атрибуты любого класса следующими способами.
Выберите в зависимости от ваших потребностей:

__dict__:

Возвращает список всех доступных для записи атрибутов класса. Обычно это то, что вам нужно.

my_obj = MyClass()
attributes = my_obj.__dict__

vars():

Тот же результат, что и __dict__, но использование этого вместо этого считается лучшей практикой.

my_obj = MyClass()
attributes = vars(my_obj)

dir():

Возвращает все атрибуты класса, включая те, которые созданы не вами, но унаследованы от object.

my_obj = MyClass()
attributes = dir(my_obj)

В вашем случае использование vars() будет работать нормально, как продемонстрировал Мартин Питерс в своем ответе.

person stybl    schedule 27.06.2017
comment
Вы упомянули vars(), но набрали dir(myObj) в этой строке: vars = dir(myObj). Это опечатка? - person Varun Verma; 28.06.2017

Похоже, вы случайно создали тип Enum.

Если ваш класс AwsRegion используется только для хранения этих значений (а не многих других сложных действий), попробуйте сделать его подклассом Enum. Это даст вам несколько хороших методов без необходимости воссоздавать все это самостоятельно и сделает ваш код более понятным для тех, кто знает, что такое перечисляемые типы.

from enum import Enum

class AwsRegion2(Enum):
    OHIO = 'us-east-2'
    NORTH_VIRGINIA = 'us-east-1'
    NORTH_CALIFORNIA = 'us-west-1'
    OREGON = 'us-west-2'
    MUMBAI = 'ap-south-1'
    SEOUL = 'ap-northeast-2'
    SINGAPORE = 'ap-southeast-1'
    SYDNEY = 'ap-southeast-2'
    TOKYO = 'ap-northeast-1'
    FRANKFURT = 'eu-central-1'
    IRELAND = 'eu-west-1'
    LONDON = 'eu-west-2'
    SAO_PAULO = 'sa-east-1'


print(list(AwsRegion2))
person Nathaniel Rivera Saul    schedule 27.06.2017