Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 16, 2010 07:24:05

gkraser
От:
Зарегистрирован: 2007-08-25
Сообщения: 57
Репутация: +  0  -
Профиль   Отправить e-mail  

autosuper

Хотелось бы вызывать 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
Теперь пример из http://python.su/forum/viewtopic.php?id=7772 работает:

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()
В чем могут быть проблемы/недостатки?



Офлайн

#2 Июнь 16, 2010 08:12:52

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

autosuper

Из-за этих пунктов смахивает на хак:
1. Метаклассы здесь не нужны (как наследование от заранее подготовленного класса).
2. Я бы не стал приватить (пусть атрибут называется __super__).

Я бы привёл вывод супера к такому виду:

...
def foo(self):
return my.utils.super()
Где my.utils некий твой модуль.
А вообще, всё это гон, зачем?

..bw



Офлайн

#3 Июнь 16, 2010 08:25:31

gkraser
От:
Зарегистрирован: 2007-08-25
Сообщения: 57
Репутация: +  0  -
Профиль   Отправить e-mail  

autosuper

bw
А вообще, всё это гон, зачем?
Хочется в python 2.6 иметь super без указания классов (как в python 3)….

Вообщем эта методика не работает: идет привязка к именам классов, из-за которой вылезут перекрытия имен _x_super при совпадении имен унаследованных классов…

А все таки: есть ли возможность иметь super без указания классов как в python 3)?



Офлайн

#4 Июнь 16, 2010 09:08:42

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

autosuper

Чепуха. Несколько лет назад пытался использовать что-то вроде http://code.activestate.com/recipes/286195-selfsuper/
Честно сказать, никакого выигрыша не ощутил. Не стоит эта возня потраченных усилий.



Офлайн

#5 Июнь 16, 2010 09:41:31

gkraser
От:
Зарегистрирован: 2007-08-25
Сообщения: 57
Репутация: +  0  -
Профиль   Отправить e-mail  

autosuper

Выгрыш - в читабельности, в унификации кода для перекрытых методов.

Этот autosuper.py я сейчас и пробую. Вроде - работает…



Офлайн

#6 Июнь 16, 2010 10:13:29

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

autosuper

О какой унификации вы говорите? Если все равно руками вбивать - то можно и имя класса при этом поменять.
Печатать меньше на пару идентификаторов. Нужно делать на один импорт больше.
Код работает немного медленней. Читать stacktrace в случае ошибки менее приятно.

Дело, конечно, господское. Я пробовал - не прижилось.



Офлайн

#7 Июнь 28, 2010 23:18:29

ilya1
От:
Зарегистрирован: 2010-06-28
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

autosuper

__super__ явно не подойдет, так как будет для всей иерархии один, а вот __super как раз то, что нужно (для каждого класса свой родитель). Описанное решение написал Guido, так что должно работать,- я пользуюсь, нравится (после C++ не могу отказаться от этого удобства).

Но и это решение критикуют, http://www.artima.com/weblogs/viewpost.jsp?thread=236278 .



Отредактировано (Июнь 28, 2010 23:18:56)

Офлайн

#8 Июнь 30, 2010 00:47:05

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

autosuper

Проясните пожалуйста, как вы использовали super в С++? Насколько я помню, такой конструкции там нет



Отредактировано (Июнь 30, 2010 00:47:43)

Офлайн

#9 Июнь 30, 2010 10:39:27

ilya1
От:
Зарегистрирован: 2010-06-28
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

autosuper

Андрей Светлов
Проясните пожалуйста, как вы использовали 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) {}
};
Замечания:
- основное применение не в конструкторах, а в виртуальных методах;
- MyParent закрыт ото всех, в первую очередь от классов-наследователей, потому вызвать метод неправильного родителя невозможно.
- вообще, фишка данного приема - не надо помнить какому классу метод принадлежит, и кто его родитель; при копи-пасте сильно помогает.



Отредактировано (Июнь 30, 2010 10:40:22)

Офлайн

#10 Июнь 30, 2010 10:51:33

ilya1
От:
Зарегистрирован: 2010-06-28
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

autosuper

Кстати, вышеуказанный 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)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version