Форум сайта python.su
Хотелось бы вызывать super без указания класса (в python 2.6).
Вот нашел решение:
class AutoSuper(type):
def __init__(cls, name, bases, dict):
super(AutoSuper, cls).__init__(name, bases, dict)
setattr(cls, "_%s__super" % name, super(cls))
class Base(object):
__metaclass__ = AutoSuper
class A(Base):
def f(self):
print 'A.f'
return None
class B(A):
def f(self):
print 'B.f'
return self.__super.f()
class C(B):
def f(self):
print 'C.f'
return self.__super.f()
Офлайн
Из-за этих пунктов смахивает на хак:
1. Метаклассы здесь не нужны (как наследование от заранее подготовленного класса).
2. Я бы не стал приватить (пусть атрибут называется __super__).
Я бы привёл вывод супера к такому виду:
...
def foo(self):
return my.utils.super()
Офлайн
bwХочется в python 2.6 иметь super без указания классов (как в python 3)….
А вообще, всё это гон, зачем?
Офлайн
Чепуха. Несколько лет назад пытался использовать что-то вроде http://code.activestate.com/recipes/286195-selfsuper/
Честно сказать, никакого выигрыша не ощутил. Не стоит эта возня потраченных усилий.
Офлайн
Выгрыш - в читабельности, в унификации кода для перекрытых методов.
Этот autosuper.py я сейчас и пробую. Вроде - работает…
Офлайн
О какой унификации вы говорите? Если все равно руками вбивать - то можно и имя класса при этом поменять.
Печатать меньше на пару идентификаторов. Нужно делать на один импорт больше.
Код работает немного медленней. Читать stacktrace в случае ошибки менее приятно.
Дело, конечно, господское. Я пробовал - не прижилось.
Офлайн
__super__ явно не подойдет, так как будет для всей иерархии один, а вот __super как раз то, что нужно (для каждого класса свой родитель). Описанное решение написал Guido, так что должно работать,- я пользуюсь, нравится (после C++ не могу отказаться от этого удобства).
Но и это решение критикуют, http://www.artima.com/weblogs/viewpost.jsp?thread=236278 .
Отредактировано (Июнь 28, 2010 23:18:56)
Офлайн
Проясните пожалуйста, как вы использовали super в С++? Насколько я помню, такой конструкции там нет
Отредактировано (Июнь 30, 2010 00:47:43)
Офлайн
Андрей СветловКонечно же в такой реализации там нет, но важна та сама идея/удобство:
Проясните пожалуйста, как вы использовали super в С++? Насколько я помню, такой конструкции там нет
class A
{
A(int) {}
};
class B: public A
{
typedef A MyParent;
public:
B(int i): MyParent(i) {}
};
class C: public B
{
typedef B MyParent;
public:
C(int i): MyParent(i) {}
};
Отредактировано (Июнь 30, 2010 10:40:22)
Офлайн
Кстати, вышеуказанный autosuper работает только для нового типа классов (порожденных от object), для классических не пройдет. А у меня, как назло, код завязан на несколько “классических” классов (пример: cmd.Cmd). Потому (из упрямства) попытался решить проблему, вышло вот так:
# Для старых классов (не порожденных от object) пользуемся так:
# make_super_for_classic_class(MyOld, Old)
# , установить после (!) описания класса MyOld
class Super(object):
''' По примеру http://www.python.org/download/releases/2.2/descrintro/#superexample '''
def __init__(self, typ, obj):
self.typ = typ
self.obj = obj
def __getattr__(self, attr):
dct = self.typ.__dict__
if attr in dct:
x = dct[attr]
if hasattr(x, "__get__"):
# привязка метода x к объекту self.obj
x = x.__get__(self.obj)
return x
raise AttributeError, attr
def make_super_for_classic_class(cls, parent_cls):
def get_super_attr(obj):
return Super(parent_cls, obj)
# добавляем атрибут __super через setattr из-за скрытности первого
# вне класса cls
setattr(cls, "_%s__super" % cls.__name__, property(get_super_attr))
class AClassic:
def func(self):
return "A"
class BClassic(AClassic):
def func(self):
return self.__super.func() + "B"
make_super_for_classic_class(BClassic, AClassic)
class CClassic(BClassic):
def func(self):
return self.__super.func() + "C"
make_super_for_classic_class(CClassic, BClassic)
eq_('ABC', CClassic().func())
Отредактировано (Июнь 30, 2010 10:54:52)
Офлайн