Можно ли печатать исходное имя переменной в Python?

Я перечислил и использовал переменные типа myEnum.SomeNameA, myEnum.SomeNameB и т.д. Когда я возвращаю одну из этих переменных из функции, могу ли я напечатать их имена (например, myEnum.SomeNameA) вместо значения, которое они вернули

Ответ 1

Короткий ответ: нет.

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

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

Ответ 2

Нет такой вещи, как уникальное или исходное имя переменной http://www.amk.ca/quotations/python-quotes/page-8

Точно так же, как вы получаете имя этой кошки, которую вы нашли на своем крыльце: сам кот (объект) не может сказать вам свое имя, и это все равно, поэтому единственный способ узнать, что это вызванный - спросить всех ваших соседей (пространства имен), если это их кошка (объект)...

.... и не удивляйтесь, если вы обнаружите, что он известен многими именами или вообще не имеет имени!

Fredrik Lundh, 3 ноября 2000 года, в ответ на вопрос "Как я могу получить имя переменной из С++, когда у меня есть PyObject *?"

Ответ 3

Чтобы добавить к @Jay answer, некоторые понятия...

"переменные" Python - это просто ссылки на значения. Каждое значение занимает определенное место памяти (см. id())

>>> id(1)
10052552

>>> sys.getrefcount(1)
569

Из вышесказанного вы можете заметить, что значение "1" присутствует в ячейке памяти 10052552. В этом случае интерпретатора указано 569 раз.

>>> MYVAR = 1
>>> sys.getrefcount(1)
570

Теперь посмотрим, что, поскольку еще одно имя связано с этим значением, счетчик ссылок увеличился на один.

Исходя из этих фактов, нереально/возможно определить, какое одно имя переменной указывает на значение.

Я думаю, что лучший способ решить вашу проблему - добавить сопоставление и функцию в ссылку enum обратно к имени строки.

myEnum.get_name(myEnum.SomeNameA) 

Прокомментируйте, пожалуйста, код образца.

Ответ 4

Просто используйте текст, который хотите напечатать, как значение перечисления, как в

class MyEnum (object):
    valueA = "valueA"
    valueB = "valueB"

сравнение строк для идентичности почти так же эффективно в Python, как и сравнение целочисленных значений (это связано с тем, что строки неизменяемы, так как имеют хеш-значение)

Конечно, есть простые способы создания перечисления в первую очередь:

class Enum (object):
    def __init__(self, *values):
        for v in values:
            self.__dict__[v] = v

Затем создайте нумерацию следующим образом:

MyEnum = Enum("valueA", "valueB")

ans доступа так же, как описано выше:

MyEnum.valueA

Ответ 5

Есть два ответа на этот вопрос: Да и Нет.

Can you do it?  -- Yes (in most cases)
Is it worth it? -- No  (in most cases)

Как это сделать:

Это зависит от реализации перечислений. Например:

class Enum:
    A = 1
    B = 2

Не имеет значения, существует ли 100 имен для целого числа, имя которого вы хотите найти, если знаете объект класса enums и все они - имена (или, по крайней мере, уникальный префикс) в этом классе.

В приведенном выше примере в качестве предлагаемого @batbrat вы можете проверить 'Enum.__dict__', используя namestr():

 >>> getEnum = lambda: Enum.A
 >>> namestr(getEnum(), Enum.__dict__)
 >>> ['A']

В этом случае вам даже не нужно знать все имена переименований. Если перечисления реализованы по-другому, вам может потребоваться использовать другой хак. В большинстве случаев будет некоторое решение, например, см. @Jay answer. Но это не имеет значения, потому что..

Стоит ли это?

  • В некоторых реализациях enum может потребоваться уродливое, сложное и, в конечном итоге, ненадежные хаки для реализации namestr().

  • Класс Enum может возвращать ответ сам по себе (см. @Дэвид, @Ber's, < Ответы href= "https://stackoverflow.com/questions/544919/python-can-i-print-original-var-name/544966#544966" > @gahooa).

  • Как @Ber указал, нет встроенного Enum и оператора switch в Python (см. PEP-0275, PEP-3103). Стоит исследовать решения без перечислений.

Ответ 6

Да.

В вашем случае с перечислениями это легко:

>>> from enum import Enum
>>> class Type(Enum):
...   AB, SBS, INTERLACED, SPLIT = range(4)
...
>>> Type.AB
<Type.AB: 0>
>>> print(Type.AB)
Type.AB
>>> Type.AB.name
'AB'
>>> Type.AB.value
0
>>> Type(0)
<Type.AB: 0>

В общем, это может быть неоднозначно:

>>> def varname(v): d = globals(); return [k for k in d if d[k] == v]
...
>>> def varnameis(v): d = globals(); return [k for k in d if d[k] is v]
...
>>> foo = {'a':'aap'}
>>> bar = {'a':'aap'}
>>> varname(foo)
['foo', 'bar']
>>> varnameis(foo)
['foo']

Или даже вводит в заблуждение:

>>> foo = "A"; bar = "A"
>>> varnameis("A")
['foo', 'bar']
>>> foo = "An immutable value."; bar = "An immutable value."
>>> varnameis("An immutable value.")
[]
>>> foo = "An immutable value."; bar = "An immutable value."; varnameis("An immutable value.")
['foo', 'bar']
>>> import sys; sys.version
'3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 02:47:15) [MSC v.1900 32 bit (Intel)]'

Для поиска в любой области используйте это:

>>> def varname(v, scope=None): d = globals() if not scope else vars(scope); return [k for k in d if d[k] == v]
...
>>> import time
>>> time.timezone
-3600
>>> varname(-3600)
[]
>>> varname(-3600, time)
['timezone']

Ответ 7

Вы можете сохранить каноническое имя как атрибут экземпляра, а затем присвоить его переменной с тем же именем. Это может сработать:

class MyEnum(object):
    def __new__(cls, name):
        try:
            return getattr(MyEnum, name)
        except AttributeError:
            e = super(MyEnum, cls).__new__(cls)
            e.name = name
            setattr(MyEnum, name, e)
            return e

Независимо от того, что это не особенно "питоническая" вещь.

Ответ 8

С другой мыслью:

Поскольку Python не предоставляет собственные типы Enum, вы не должны запрашивать его, а вместо этого используете другую более мощную конструкцию для создания вашей программы. В противном случае следующий шаг будет неизменно "Почему Python не имеет оператора switch ...: и как его лучше всего эмулировать?"

Так как Enums часто используются для определения какого-то состояния, гораздо лучший подход заключается в следующем: Создайте базовый класс, который определяет все абстрактные свойства, атрибуты и методы, принадлежащие государству. Затем для каждого состояния выводится подкласс, который реализует конкретное поведение этого состояния. Затем вы можете обойти эти классы (или, возможно, их экземпляры), для обработки состояния и его поведения.

Если вы используете классы вместо экземпляров (способ Python для "singleton" ), вы можете просто проверить какое-либо состояние (не то, что это необходимо) на if current_state is StateA: (обратите внимание на is вместо ==) без штрафа за производительность при сравнении целых значений.

И, конечно, вы можете определить атрибут name и метод __str__() для доступа и печати имени состояния.

Ответ 9

Насколько я знаю, это потребует некоторой интроспекции. Вы можете попробовать использовать модуль проверки.

Есть несколько простых вещей, которые вы можете попробовать до этого:

  •   
  • Это не точный код, который следует использовать. Вам нужно будет получить имя переменной из __dict__ перед печатью.       
    print myEnum.__dict__
            
        
  •       Если вы хотите напечатать имя переменной внутри функции, вы можете попробовать       функции - vars(), locals() и globals().       
    Изменить:
          Я только заметил, что это не то, что вы хотите. В этом случае добавление       dict и функция может работать      
  •       Вы можете распечатать __dict__ класса ваших перечислений.   

Все, что сказано, в Python нет стандартных перечислений. Это поможет узнать, как вы их создаете.

Во-вторых, вы можете сохранить свои переменные в виде словаря в перечислении, с ключом по имени переменной и предоставить метод перечисления, чтобы найти правильную переменную и напечатать ее имя. Это решение (сохранение dict) плохо, потому что переменные значения необязательно уникальны.

Изменить:
Проблема не является тривиальной, поэтому вы можете использовать проверенное и проверенное решение. ИМХО, вам лучше избегать ситуации, если сможете.

Ответ 10

Эрланг имеет понятие "атомы" - они похожи на строковые константы или перечисления. Рассмотрите возможность использования строковой константы в качестве значения вашего перечисления - то же самое, что и имя перечисления.

Ответ 11

ДА

import inspect

def printVariableName(abc):
    newvar=inspect.stack()[1][4][0]
    print(newvar.split("(")[1].split(")")[0])

noob=10
printVariableName(noob)

Выход:

noob

Ответ 12

Python 3.8 добавил новое и, возможно, НЕМНОГО лучшее решение для этого:

my_nice_variable_name = 'test'
print(f'{my_nice_variable_name=}')

# Output:
# my_nice_variable_name='test'

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