Я перечислил и использовал переменные типа myEnum.SomeNameA
, myEnum.SomeNameB
и т.д. Когда я возвращаю одну из этих переменных из функции, могу ли я напечатать их имена (например, myEnum.SomeNameA
) вместо значения, которое они вернули
Можно ли печатать исходное имя переменной в Python?
Ответ 1
Короткий ответ: нет.
Длинный ответ: это возможно с некоторыми уродливыми хаками, использующими трассировку, проверку и т.п., но обычно это не рекомендуется для производственного кода. Например, см.
- http://groups.google.com/group/comp.lang.python/msg/237dc92f3629dd9a?pli=1
- http://aspn.activestate.com/ASPN/Mail/Message/python-Tutor/330294
Возможно, вы можете использовать обходное решение для перевода значения обратно в строку имени/репрезентации. Если вы разместите еще несколько примеров кода и подробностей о том, чего вы хотите, возможно, мы сможем предоставить более глубокую помощь.
Ответ 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'
Здесь вы можете работать со строковым выводом. Все еще не рекомендуется, но, возможно, немного лучше, чем другие способы сделать это.