Я могу распечатать имя исходной переменной в Python?

Q1. sub rsp, 32

blockquote>

Это выделяемое пространство, которое используется для хранения некоторых данных. Хотя он выделяет 32 байта, код использует только первые 16 байтов этого выделенного пространства, qword в [rbp-8] (0: edi) и qword в [rbp-16] (rdi).

Q2. lea rax, [rip + L_.str] и mov rdi, rax

blockquote>

Леа получает адрес строки, хранящейся в сегменте «код». Он перемещен в rdi, который используется в качестве одного из параметров для printf.

Q3. mov dword ptr [rbp - 4], 0 ... mov dword ptr [rbp - 8], edi

blockquote>

В нем хранится 64-разрядное значение с прямым порядком байтов, состоящее из 0: edi в [rbp - 8]. Я не уверен, почему он это делает, так как он никогда не загружается из этого слова позже.

Обычно неоптимизированный код хранит свои аргументы регистра в памяти, где отладочная информация может указывать отладчикам, где их искать и изменять, но неясно, почему clang ноль расширяет argc в edi до 64 бит) .

Скорее всего, 0 dword - это нечто отдельное, потому что, если компилятор действительно хотел хранить расширение с нулем argc, компиляторы будут расширяться с нуля в регистрах с 32-битным mov, как mov ecx, edi ]; mov [rbp-8], rcx. Возможно, этот дополнительный ноль является временным возвращаемым значением, которое он позже решает не использовать из-за явного return 0; вместо неявного падения с конца main? (main особенный, и я думаю, что clang создает внутреннюю временную переменную для возвращаемого значения.)

Q4 mov qword ptr [rbp - 16], rsi ... mov rsi, qword ptr [rbp - 16]

blockquote>

Оптимизация выключена? Он сохраняет rsi, затем загружает rsi из [rbp - 16]. rsi содержит вашу функцию argv arg (== &argv[0]). x86-64 System V ABI передает целочисленные значения / указатели в RDI, RSI, RDX, RCX, R8, R9, затем в стек .

... mov rsi, qword ptr [rsi + 8]

blockquote>

Это загрузка rsi с содержимым argv[1], как 2-й аргумент для printf. (По той же причине, по которой второй аргумент main был в rsi).

Соглашение о вызовах x86-64 System V также является причиной обнуления AL перед вызовом функции varargs без аргументов FP.

Q5. mov dword ptr [rbp - 20], eax

blockquote>

Оптимизация выключена? Он хранит возвращаемое значение из printf, но никогда не использует его.

51
задан Piotr Dobrogost 16 September 2013 в 00:06
поделиться

11 ответов

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

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

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

32
ответ дан S.Lott 7 November 2019 в 10:09
поделиться

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

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

.... и не удивлены, найдете ли Вы, что это известно многими именами или никаким именем вообще!

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

25
ответ дан Johan Buret 7 November 2019 в 10:09
поделиться

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

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

>>> id(1)
10052552

>>> sys.getrefcount(1)
569

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

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

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

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

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

myEnum.get_name(myEnum.SomeNameA) 

прокомментируйте, хотели ли бы Вы пример кода.

23
ответ дан Community 7 November 2019 в 10:09
поделиться

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

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")

ответ получают доступ к тому же пути как выше:

MyEnum.valueA
5
ответ дан Benjamin 7 November 2019 в 10:09
поделиться

Существует два ответа на этот вопрос: Да и Никакой .

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

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

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

class Enum:
    A = 1
    B = 2

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

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

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

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

это стоящий того?

3
ответ дан Community 7 November 2019 в 10:09
поделиться

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

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

Невнимательный, это не особенно вещь "Pythonic" сделать.

2
ответ дан David Z 7 November 2019 в 10:09
поделиться

Вообще-то, если задуматься:

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

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

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

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

1
ответ дан Benjamin 7 November 2019 в 10:09
поделиться

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

0
ответ дан gahooa 7 November 2019 в 10:09
поделиться

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

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

  1. Это не точный код, который должен использоваться. Необходимо будет получить имя переменной от __ dict __ перед печатью.
    print myEnum.__dict__
            
  2. , Если Вы хотите распечатать имя переменной из функции, можно попробовать функции - Вар (), местные жители () и globals ().
    Редактирование :
    я просто заметил, что это не то, что Вы хотите. В этом случае добавление dict и функции может работать
  3. , можно хотеть распечатать __ dict __ класса перечислений.

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

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

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

0
ответ дан batbrat 7 November 2019 в 10:09
поделиться

ДА

import inspect

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

noob=10
printVariableName(noob)

Вывод:

noob
0
ответ дан 7 November 2019 в 10:09
поделиться

Python 3.8 добавил новое и вероятно МАЛО лучшее решение этого:

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

# Output:
# my_nice_variable_name='test'

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

0
ответ дан 7 November 2019 в 10:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: