Monkeypatching пространство имен функции

Вдохновленный «Определить @property для функции» , я попытался переопределить пространство имен функции:

>>> class MyDict(dict):
...     def __getitem__(self, item):
...         if item == 'k2':
...             return 'v2'
...         return super().__getitem__(item)
...     
>>> def f():
...     pass
... 
... 
>>> f.__dict__ = MyDict({'k1': 'v1'})
>>> 
>>> f.k1
'v1'
>>> f.k2
AttributeError: 'function' object has no attribute 'k2'

Почему f.k1 разрешается, но f.k2 не могу?

4 голоса | спросил wim 23 Mayam18 2018, 03:19:26

2 ответа


0
Краткая версия: поскольку функция CPython ---- +: = 0 =: + ---- не подходит для подклассов (она не предназначена для ясности; ---- +: = 1 =: + -- все функции являются специализированными для ---- +: = 2 =: + ---- , а не для обобщенных отображений).Длинная версия: получение атрибута вызывает ---- +: = 3 =: + ---- .Для классов, которые явно не определяют пользовательские ---- +: = 4 =: + ---- или ---- +: = 5 =: + ---- (и ---- +: =6 =: + ---- нет ), в итоге вызывается ---- +: = 7 =: + ---- .Предполагая, что ничего не найдено в самом классе, ---- +: = 8 =: + ---- (ну, частная API-функция, которая его реализует) получает ---- +: = 9 =: + ---- как обычно, затем вызывает ---- +: = 10 =: + ----, чтобы получить значение .---- +: = 11 =: + ---- явно использует ---- +: = 12 =: + ---- внутренности уровня C для выполнения доступа, минуя любой пользовательский ----+: = 13 =: + ---- вы могли бы определить.Так что ваш обычай ---- +: = 14 =: + ---- никогда не вызывается;для всех практических целей ваш подкласс ---- +: = 15 =: + ---- - это просто ---- +: = 16 =: + ---- .Изначально я надеялся , что вы могли бы сделать этот конкретный случай работы через официально поддерживается ---- +: = 17 =: + ---- крючке , но оказывается, что это только вызывается , когда эквивалент ----+: = 18 =: + ---- ( ---- +: = 19 =: + ---- ) вызывается не через API прямого доступа уровня C, например ---- +: = 20 =:+ ---- (которые не проходят ---- +: = 21 =: + ---- вообще).По сути, CPython, похоже, сделал выбор в пользу приоритизации производительности перед полной гибкостью.Любой ---- +: = 22 =: + ---- подкласс, используемый как ---- +: = 23 =: + ----, будет доступен, как если бы он был простым ---- +: =24 =: + ---- (что может немного усложнить, если подкласс выполняет какое-то волшебство, чтобы сохранить одно значение, притворяясь, что оно хранит другое значение, так как магия обойдена), и все сопоставления, которые не -- +: = 25 =: + ---- подклассы отклоняются во время назначения (вы получаете ---- +: = 26 =: + ---- при попытке назначить их на ----+: = 27 =: + ---- ).
ответил ShadowRanger 23 Mayam18 2018, 03:56:00
0
Первое предложение в документации для ---- +: = 0 =: + ---- гласит: «Вызван для реализации оценки себя [ключ].»Вы предполагаете (надеетесь), что оценка ---- +: = 1 =: + ---- выполняет явную операцию ---- +: = 2 =: + ---- , но это не так,Если вы поместите оператор print в первую строку ---- +: = 3 =: + ----, вы увидите, что эта функция никогда не вызывается вашим кодом.Я не уверен, почему это так, но я подозреваю, что это по соображениям производительности.В любом случае, я не могу придумать хороший вариант использования для замены функции ---- +: = 4 =: + ---- .Есть слишком много способов, которые могут потерпеть неудачу.
ответил Paul Cornelius 23 Mayam18 2018, 03:55:20

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132