Специальные методы, такие как __contains__
, являются специальными, только когда они определены в классе, но не в экземпляре (за исключением устаревших классов в Python 2, которые вы должны не использовать в любом случае).
Итак, ваша делегация на уровне класса:
class A(object):
def __init__(self):
self.mydict = {}
def __contains__(self, other):
return self.mydict.__contains__(other)
Я бы предпочел записать последнее как return other in self.mydict
, но это незначительная проблема стиля.
Редактировать : если и когда «абсолютно динамическое перенаправление для каждого экземпляра специальных методов» (например, предлагаемые классы старого стиля) необходимо, это не сложно реализовать с помощью классов нового стиля: вы просто нужно, чтобы каждый экземпляр, который имеет такую особенность, был обернут в свой специальный класс. Например:
class BlackMagic(object):
def __init__(self):
self.mydict = {}
self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
self.__class__.__contains__ = self.mydict.__contains__
По сути, после небольшой чёрной магии переназначение self.__class__
на новый объект класса (который ведет себя так же, как и предыдущий, но имеет пустой dict и никаких других экземпляров, кроме этого self
), где-нибудь в старом -стиль класса, который вы бы присвоили self.__magicname__
, вместо этого присвойте self.__class__.__magicname__
(и убедитесь, что это встроенная или staticmethod
, а не обычная функция Python, если, конечно, в другом случае вы не хотите, чтобы она получала self
при вызове экземпляра).
Между прочим, оператор in
в экземпляре этого класса BlackMagic
на быстрее , как это бывает, чем с любым из ранее предложенных решений - или, по крайней мере, так я измеряю с моим обычным верным -mtimeit
(переходя непосредственно к built-in method
, вместо того, чтобы следовать обычным маршрутам поиска, включающим наследование и дескрипторы, снимает немного накладных расходов).
Метакласс для автоматизации идеи self.__class__
-per-instance написать несложно (он может выполнить грязную работу в методе __new__
сгенерированного класса и, возможно, также установить все магические имена, которые фактически назначаются на класс, если он назначен экземпляру, либо через __setattr__
, либо через многие свойства many ). Но это было бы оправдано, только если бы потребность в этой функции была действительно широко распространена (например, портирование огромного древнего проекта Python 1.5.2, который свободно использует «специальные методы для каждого экземпляра», на современный Python, включая Python 3).
Рекомендую ли "умные" или "черные магические" решения? Нет, не знаю: почти всегда лучше делать вещи простыми и понятными способами. Но слово «почти» здесь очень важно, и приятно иметь под рукой такие продвинутые «зацепки» для редких, но не несуществующих ситуаций, где их использование действительно оправдано.