Как я добавляю атрибуты к методу во времени выполнения?

Я опаздываю, но вы хотите получить какой-то источник с вашим ответом? *

Хорошо, что в 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) call get_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.


* - Я попробую и слово это более вводным образом, чтобы большинство могло следовать дальше.

14
задан Simon 20 November 2008 в 08:49
поделиться

4 ответа

То, чего Вы пытаетесь достигнуть, вполне сложно, таким образом, я попытаюсь обеспечить что-то только для запущения Вас. Это - то, что я думаю, что необходимо было бы объединиться для достижения чего-то:

  1. Определяют абстрактный класс AbstractEventDebugger, с методом Search, который ищет все из эти event участники и регистрирует их в EventInspector. Кроме того, определите метод IdentifyEvent, который позволит Вам определять событие, которое назвало его (это зависит от Вас - что параметры будут иметь, и т.д.).
  2. Определяют dynamic type использование TypeBuilder (как описано здесь ), который наследовался Вашему классу. Этот класс был бы классом Вашего debugger объект.
  3. Присоединение Обработчики к Вашему классу с помощью Reflection.Emit.MethodBuilder (см. здесь ), который будет звонить IdentifyEvent метод от родительского класса и,
  4. Reflection.Emit атрибуты на обработчиках с помощью [1 110] класс (см. здесь ).
  5. Создают экземпляр Вашего dynamic класс и отправляют его EventInspector.
  6. Огонь это :)

Здесь является образец о том, как создать метод, который называет что-то (На самом деле, это - классик "Привет мир").

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

Удачи!

10
ответ дан 1 December 2019 в 14:12
поделиться

Атрибуты являются функцией времени компиляции (если Вы не имеете дело с ComponentModel - но я подозреваю, что он использует отражение). По сути, Вы не можете добавить атрибуты во времени выполнения. Это было бы подобный вопрос, "как я добавляю дополнительный метод к типу во времени выполнения?". В регулярном C#/.NET (предварительный доллар), Вы не можете.

3
ответ дан 1 December 2019 в 14:12
поделиться

Необходимо копаться в мире DynamicMethod . Однако, поскольку необходимо затем знать MSIL, я действительно предлагаю, чтобы Вы думали трудно о своей архитектуре.

1
ответ дан 1 December 2019 в 14:12
поделиться

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, у Вас есть много опций. Я рекомендовал бы проверить следующую статью:

Отладка кода с TraceSource Мой Persoanl Vade Mecum

1
ответ дан 1 December 2019 в 14:12
поделиться
Другие вопросы по тегам:

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