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, но никогда не использует его.
Короткий ответ: нет.
ответ Long: это возможно с некоторыми ужасными взломами с помощью traceback, осмотрите и т.п., но это обычно, вероятно, не рекомендуется для производственного кода. Например, см.:
, Возможно, можно использовать обходное решение для перевода значения назад в строку имени / представительную строку. Если Вы отправляете некоторый более пример кода и детали о том, для чего Вы желаете это, возможно, мы можем оказать больше всесторонней помощи.
Нет такой вещи как уникальное или исходное имя переменной http://www.amk.ca/quotations/python-quotes/page-8
тот же путь, как Вы получаете имя той кошки, которую Вы нашли на своем подъезде: кошка сам (объект) не может сказать Вам свое имя, и это действительно не заботится - так единственный способ узнать то, чем это называют, должны спросить все Ваши соседи (пространства имен), если это - их кошка (объект)...
.... и не удивлены, найдете ли Вы, что это известно многими именами или никаким именем вообще!
Fredrik Lundh, 3 ноября 2000, в ответе на вопрос, "Как я могу получить название переменной от C++, когда у меня есть PyObject*?"
Добавить к ответ @Jay , некоторые понятия...
Python "переменные" просто ссылки на значения. Каждое значение занимает данную ячейку памяти (см. id()
)
>>> id(1)
10052552
>>> sys.getrefcount(1)
569
От вышеупомянутого, можно заметить, что значение "1" присутствует в ячейке памяти 10052552. Это отнесено в 569 раз в этом экземпляре интерпретатора.
>>> MYVAR = 1
>>> sys.getrefcount(1)
570
Теперь, посмотрите, что, потому что еще одно имя связывается с этим значением, подсчет ссылок повысился одним.
На основе этих фактов, не реалистически/возможно сказать, какое единственное имя переменной указывает на значение.
я думаю, что лучший способ решить Вашу проблему состоит в том, чтобы добавить отображение и функцию к Вашей перечислимой ссылке назад на имя строки.
myEnum.get_name(myEnum.SomeNameA)
прокомментируйте, хотели ли бы Вы пример кода.
Просто используйте текст, который Вы хотите распечатать как значение перечисления, как в
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
Существует два ответа на этот вопрос: Да и Никакой .
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 . Но это не имеет значения потому что..
Некоторые перечислимые реализации могут потребовать ужасный, сложный и в конце ненадежные взломы реализовывать namestr()
.
Класс Enum может дать ответ отдельно (см. @David , @Ber , @gahooa ответы).
Как [1 112] @Ber указал нет никакого встроенного Перечислимого и оператора переключения в Python (см. PEP-0275, PEP-3103). Стоит исследовать решения без перечислений.
Вы могли сохранить каноническое имя как атрибут экземпляра и затем присвоить его переменной с тем же именем. Это могло бы работать:
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" сделать.
Вообще-то, если задуматься:
, Так как Python не обеспечивает собственные Перечислимые типы, Вы не должны просить одного, но вместо этого использовать другой, более мощная конструкция для создания программы. Иначе следующий шаг неизменно будет, "Почему Python не имеет switch ...:
оператор, и как прилагают все усилия, эмулируют его?"
, Так как Перечисления часто используются для определения некоторого состояния, намного лучший подход - это: Создайте базовый класс, которые определяют все абстрактные свойства, атрибуты и методы, принадлежащие состоянию. Затем для каждого состояния получите sub класс, который реализует определенное поведение этого состояния. Можно затем раздать эти классы (или возможно экземпляры этого) для обработки состояния и его поведения.
при использовании классов вместо экземпляров (Python способ "одиночного элемента") можно просто проверить на любое данное состояние (не, что это должно быть необходимо) if current_state is StateA:
(отметьте is
вместо ==
) без потери производительности по сравнению целочисленных значений.
И конечно, можно определить name
атрибут и __str__()
метод, чтобы получить доступ и распечатать имя состояния.
Erlang имеет понятие, названное "атомами" - они подобны строковым константам или перечислениям. Рассмотрите использование строковой константы как значения Вашего перечисления - то же как название перечисления.
Насколько я знаю, это потребует некоторого самоанализа. Можно попытаться использовать осмотреть модуль.
существует несколько простых вещей, которые можно хотеть попробовать перед этим:
print myEnum.__dict__
Однако в Python нет стандартных перечислений. Это помогло бы знать, как Вы создаете их.
Поразмыслив, можно поддержать переменные как словарь в перечислении, включенном именем переменной, и предоставить метод перечисления, чтобы найти правильную переменную и распечатать ее имя. Это решение (сохраняющий dict) плохо, потому что значения переменных не обязательно уникальны.
Редактирование :
проблема не тривиальна, таким образом, можно хотеть использовать проверенное на практике решение. По моему скромному мнению, Вы были бы более обеспеченным предотвращением ситуации, если Вы можете.
import inspect
def printVariableName(abc):
newvar=inspect.stack()[1][4][0]
print(newvar.split("(")[1].split(")")[0])
noob=10
printVariableName(noob)
Вывод:
noob
Python 3.8 добавил новое и вероятно МАЛО лучшее решение этого:
my_nice_variable_name = 'test'
print(f'{my_nice_variable_name=}')
# Output:
# my_nice_variable_name='test'
Здесь Вы могли работать со строковым выводом. Все еще не желательный, но возможно немного лучше, чем другие способы сделать его.