Не совсем понятно, что вы пытаетесь сделать. Я подозреваю, что вы хотите написать код что-то вроде
class Foo(object):
def __init__(self, name):
self.name = name
def method_1(self, bar):
print self.name, bar
# ... something here
my_foo = Foo('baz')
my_foo.methods[1]('quux')
# prints "baz quux"
так, что атрибут methods
должен каким-то образом возвращать связанный метод экземпляра, но без непосредственного вызова. Это хорошая возможность использовать descriptor
. Нам нужно сделать что-то, что будет возвращать специальный объект при доступе через экземпляр, и нам нужен этот специальный объект, чтобы возвращать связанный метод при индексации. Давайте начнем изнутри и продолжим наш путь.
>>> import types
>>> class BindMapping(object):
... def __init__(self, instance, mapping):
... self.instance, self.mapping = instance, mapping
...
... def __getitem__(self, key):
... func = self.mapping[key]
... if isinstance(func, types.MethodType):
... return types.MethodType(func.im_func, self.instance, func.im_class)
... else:
... return types.MethodType(func, self.instance, type(self))
...
Мы просто реализуем минимальный протокол сопоставления и полностью откладываем базовую коллекцию. здесь мы используем types.MethodType
для получения реального метода экземпляра, когда это необходимо, включая привязку чего-то, что уже является методом экземпляра. Посмотрим, как это будет полезно через минуту.
Мы могли бы реализовать дескриптор напрямую, но для целей здесь, property
уже делает все, что нам нужно, из дескриптора, поэтому мы просто определим тот, который возвращает правильно построенный экземпляр BindMapping
.
>>> class Foo(object):
... def method_1(self):
... print "1"
... def method_2(self):
... print "2"
...
... _mapping = [method_1, method_2]
...
... @property
... def mapping(self):
... return BindMapping(self, self._mapping)
...
Только для пинка мы также добавляем несколько дополнительных методов вне тела класса. Обратите внимание, что методы, добавленные внутри тела класса, являются функциями, точно так же как функции, добавленные снаружи; методы, добавленные вне тела класса, являются фактическими методами экземпляра (хотя и не связаны).
>>> def method_3(self):
... print "3"
...
>>> Foo._mapping.append(method_3)
>>> Foo._mapping.append(Foo.method_1)
>>> map(type, Foo._mapping)
[<type 'function'>, <type 'function'>, <type 'function'>, <type 'instancemethod'>]
И это работает как рекламируется:
>>> f = Foo()
>>> for i in range(len(f._mapping)):
... f.mapping[i]()
...
1
2
3
1
>>>