Я опаздываю, но вы хотите получить какой-то источник с вашим ответом? *
Хорошо, что в CPython вы можете увидеть источник этого. На данный момент я собираюсь использовать ссылки для релиза 3.5
; поиск соответствующих 2.x
является тривиальным.
В CPython функция C-API
, которая обрабатывает создание нового объекта int
, - PyLong_FromLong(long v)
. Описание этой функции:
Текущая реализация хранит массив целых объектов для всех целых чисел от -5 до 256, когда вы создаете int в этом диапазоне, который вы на самом деле просто получаете назад ссылку на существующий объект . Поэтому должно быть возможно изменить значение 1. Я подозреваю, что поведение Python в этом случае не определено. : -)
blockquote>Не знаю о вас, но я вижу это и думаю: Найдем этот массив!
Если у вас есть " t fiddled с кодом
C
, реализующим CPython , вы должны , все довольно организовано и доступно для чтения. Для нашего случая нам нужно посмотреть в подкаталогеObjects/
дерева каталогов основного исходного кода .
PyLong_FromLong
имеет дело сlong
, поэтому нетрудно вывести, что нам нужно заглянуть внутрьlongobject.c
. Посмотрев внутрь, вы можете подумать, что вещи хаотичны; они, но не боятся, функция, которую мы ищем, пугает вline 230
, ожидая, что мы это проверим. Это небольшая функция, поэтому основное тело (исключая декларации) легко вставлено здесь:PyObject * PyLong_FromLong(long ival) { // omitting declarations CHECK_SMALL_INT(ival); if (ival < 0) { /* negate: cant write this as abs_ival = -ival since that invokes undefined behaviour when ival is LONG_MIN */ abs_ival = 0U-(unsigned long)ival; sign = -1; } else { abs_ival = (unsigned long)ival; } /* Fast path for single-digit ints */ if (!(abs_ival >> PyLong_SHIFT)) { v = _PyLong_New(1); if (v) { Py_SIZE(v) = sign; v->ob_digit[0] = Py_SAFE_DOWNCAST( abs_ival, unsigned long, digit); } return (PyObject*)v; }
Теперь мы не
C
master-code-haxxorz , но мы «Также не глупый, мы можем видеть, чтоCHECK_SMALL_INT(ival);
заглядывает к нам все соблазнительно; мы можем понять, что это как-то связано с этим. Давайте посмотрим:#define CHECK_SMALL_INT(ival) \ do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \ return get_small_int((sdigit)ival); \ } while(0)
Итак, это макрос, который вызывает функцию
get_small_int
, если значениеival
удовлетворяет условию:if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS)
Итак, каковы
NSMALLNEGINTS
иNSMALLPOSINTS
? Если вы догадались о макросах, вы ничего не получаете, потому что это не был таким сложным вопросом. В любом случае, здесь они :#ifndef NSMALLPOSINTS #define NSMALLPOSINTS 257 #endif #ifndef NSMALLNEGINTS #define NSMALLNEGINTS 5 #endif
Итак, наши состояние -
if (-5 <= ival && ival < 257)
callget_small_int
.Некуда идти, но продолжайте наше путешествие, взглянув на
get_small_int
во всей красе (ну, мы просто посмотрим на это тело, потому что это были интересные вещи ):PyObject *v; assert(-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS); v = (PyObject *)&small_ints[ival + NSMALLNEGINTS]; Py_INCREF(v);
Хорошо, объявите
PyObject
, утвердите, что предыдущее условие выполнено и выполняет назначение:v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];
small_ints
выглядит так же, как массив, который мы искали .. и это! Мы могли бы просто прочитать проклятую документацию, и мы все знали бы! :/* Small integers are preallocated in this array so that they can be shared. The integers that are preallocated are those in the range -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive). */ static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
Так что, это наш парень , Когда вы хотите создать новый
int
в диапазоне[NSMALLNEGINTS, NSMALLPOSINTS)
, вы просто вернете ссылку на уже существующий объект, который был предварительно выделен.Поскольку ссылка ссылается на один и тот же объект, выдача
id()
непосредственно или проверка подлинности сis
на нем вернет точно то же самое.Но когда они выделены ??
Во время инициализации в
_PyLong_Init
Python с радостью войдет в цикл for, сделайте это для вас:for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++, v++) { // Look me up! }
Надеюсь, мои объяснения заставили вас
C
(каламбур явно задуматься) теперь ясно.Но, 257 - 257? Что случилось?
Это на самом деле проще объяснить, , и я уже пытался сделать это ; это связано с тем, что Python выполнит этот интерактивный оператор:
>>> 257 is 257
как один блок. Во время компиляции этого утверждения CPython увидит, что у вас есть два подходящих литерала, и будет использовать тот же
PyLongObject
, представляющий257
. Вы можете это увидеть, если сами делаете компиляцию и изучаете ее содержимое:>>> codeObj = compile("257 is 257", "blah!", "exec") >>> codeObj.co_consts (257, None)
Когда CPython выполняет операцию; теперь он будет загружать тот же самый объект:
>>> import dis >>> dis.dis(codeObj) 1 0 LOAD_CONST 0 (257) # dis 3 LOAD_CONST 0 (257) # dis again 6 COMPARE_OP 8 (is)
Таким образом,
is
вернетTrue
.* - Я попробую и слово это более вводным образом, чтобы большинство могло следовать дальше.
То, чего Вы пытаетесь достигнуть, вполне сложно, таким образом, я попытаюсь обеспечить что-то только для запущения Вас. Это - то, что я думаю, что необходимо было бы объединиться для достижения чего-то:
AbstractEventDebugger
, с методом Search
, который ищет все из эти event
участники и регистрирует их в EventInspector. Кроме того, определите метод IdentifyEvent
, который позволит Вам определять событие, которое назвало его (это зависит от Вас - что параметры будут иметь, и т.д.). dynamic type
использование TypeBuilder
(как описано здесь ), который наследовался Вашему классу. Этот класс был бы классом Вашего debugger
объект. Reflection.Emit.MethodBuilder
(см. здесь ), который будет звонить IdentifyEvent
метод от родительского класса и, Reflection.Emit
атрибуты на обработчиках с помощью [1 110] класс (см. здесь ). dynamic
класс и отправляют его EventInspector. :)
Здесь является образец о том, как создать метод, который называет что-то (На самом деле, это - классик "Привет мир").
необходимо будет сделать большую тонкую настройку для получения преуспевшего, но Вы узнаете много об отражении.
Удачи!
Атрибуты являются функцией времени компиляции (если Вы не имеете дело с ComponentModel - но я подозреваю, что он использует отражение). По сути, Вы не можете добавить атрибуты во времени выполнения. Это было бы подобный вопрос, "как я добавляю дополнительный метод к типу во времени выполнения?". В регулярном C#/.NET (предварительный доллар), Вы не можете.
Необходимо копаться в мире DynamicMethod
. Однако, поскольку необходимо затем знать MSIL, я действительно предлагаю, чтобы Вы думали трудно о своей архитектуре.
EventInspector использует EventTopics (которые хранятся в WorkItem) сделать весь тяжелый подъем. Каждый объект EventTopic имеет доступ к TraceSource, названному
Microsoft. Методы. CompositeUI.EventBroker. EventTopic
, Который можно включить в app.config файле как это:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<switches>
<add name="Microsoft.Practices.CompositeUI.EventBroker.EventTopic" value="All" />
</switches>
</system.diagnostics>
</configuration>
Это должно заставить много полезных сообщений направляться к Вашему окну отладки в Visual Studio. Если Вы хотите пойти вне окна отладки VS, у Вас есть много опций. Я рекомендовал бы проверить следующую статью: