LINUX.ORG.RU

Программирование метаклассов в Python


0

0

Большинство читателей уже знакомо с концепциями объектно-ориентированного программирования: наследованием, инкапсуляцией, полиморфизмом. Однако обычно при этом подразумевается создание объектов заданного класса с определенными родителями. С другой стороны, выясняется, что ряд новых программных конструкций оказывается легче или вообще возможно создавать, только если мы можем настраивать сам процесс создания объектов. Метаклассы открывают возможность определенных типов "аспект-ориентированного программирования", например, вы можете расширять классы новыми возможностями трассировки, сохранения объектов, протоколирования ошибок и т.д.

>>> Подробности

★★★

Проверено: maxcom ()

Кто сможет мне человеческим языком объяснить, что такое аспектно-ориентированное программирование, тому пряник.

ero-sennin ★★
()

пистон ненужен. даешь язык состоящий только из пробелов!!

anonymous
()
Ответ на: комментарий от ero-sennin

Ну, например, есть у тебя какой-то класс. И надо тебе добавить в него измерение времени выполнения методов. Вот ты создаёшь аспект (класс или целую систему) и присобачиваешь его (НА УРОВНЕ КОНФИГУРАЦИИ) к своему классу и этот аспект печатает время выполнения определенных методов твоего класса в лог файл. А когда всё отлажено, то на стадии деплоймента просто убераешь это из конфигурации и твой класс даже не знает что его мерили :)

dimag
()

А зачем это надо? Разве что если в голове каша...

Вообще то говоря строго в Питоне нет никаких классов. Хотя бы на том основании что любая функция или переменная использованная после создания класса может быть его членом. Иначе говоря никакой инкапсуляции данных в классы Питон не предлагает в этой связи само понятие класс теряет смысл.

Любой класс или объект должен обладать определёнными свойствами. Добавление свойств и действий на ходу убивает весь изначальный смысл.

Для использования исходных классов в своих задачах придумана наследственность. А так получаем полную кашу.

lefsha
()
Ответ на: комментарий от ero-sennin

> Кто сможет мне человеческим языком объяснить, что такое аспектно-ориентированное программирование, тому пряник.

Есть такое понятие, cross-cutting aspect, таковыми являются управление транзакциями, логирование, управление безопасностью и др. По сути это дублирующийся одинаковый код в начале и конце вызова методов. Логично, что дублирование кода не является хорошим стилем программирования, поэтому и применяются аспекты, которые позволяют в определённый момент выполнения программы (вызов метода, выход из метода, возникновение ислючения, изменение поля объекта и т.п.) выполнить определённые действия, тем самым изменяя поведение метода и наделяя его новыми свойствами. Как-то так...

Bohtvaroh ★★★★
()
Ответ на: комментарий от lefsha

>А так это никак не сделать... До этого все люди мучились и думали как бы им бедным класс померить...

А глобальнее подумать? Или думалка забита ПХП мусором?

dimag
()
Ответ на: комментарий от Sun-ch

> В лиспе это называет модификаторы after и before?

С поправкой на то, что обработка аспекта пишется один раз и потом подключается ко всем "подходящим" классам чисто декларативно. Ну и на то, что только before- и after- случаями там дело не ограничивается.

anonymous
()
Ответ на: комментарий от dimag

А глобальнее подумать? Или думалка забита ПХП мусором?

Это единственный язык, о котором Вы знаете кроме Питона? Ну что ж и такое бывает...

Хотя причем тут конкретный язык непонятно...

Думать же глобально хорошо только за пивом. Во всех остальных случаях устремления в эту сторону должны караться.

lefsha
()

ООП не нужно...

imp ★★
()

> Python 1.5.2 (#0, Jun 27 1999, 11:23:01) [...]

Убило ;) Привет тебе, шестой редхат! Помню, большая проблема в то время была - как раз питон изучал, во всех книгах (diveintopython в частности, с которого начинал) уже про второй было рассказано, а в дистрибутиве все еще 1.5, чтоб его.. Разница-то ощутимая была, особенно между 1.5 и 2.1.

anonymous
()
Ответ на: комментарий от ero-sennin

> что такое аспектно-ориентированное программирование

Возможность обернуть заданным кодом вызов любого набора функций/методов,

tailgunner ★★★★★
()

зачем это если есть exec

shafff
()

А есть какой-нибудь язык, где классов как абстрактного типа не было бы вовсе, а были бы некие функции-конструкторы, возвращающие некую разновидность хэш-таблицы со ссылками на методы? И чтобы полиморфизм работал не путём проверки типа, а по принципу "есть такой метод в этой таблице -- хорошо, нет -- увы". Ну можно ещё добавить возможность поэлементного сопоставления с неким шаблоном... Ну видоизменять эту таблицу, естественно, должно быть можно.

Детский пример: есть объект "осёл" и объект "петух". Первый имеет метод "бежать", второй -- "лететь". И оба -- метод "кричать". И я не хочу задумываться о происхождении этих объектов и наличии общего предка. Я хочу только вызвать метод "кричать", а поскольку оба объекта оный имеют, то _в данном контексте_ они совместимы.

Вот такой язык хочу для себя, для души.

AsphyX ★★★
()
Ответ на: комментарий от Sun-ch

> В лиспе это называет модификаторы after и before?

Нет, around 8)

tailgunner ★★★★★
()
Ответ на: комментарий от AsphyX

Java :)

Ты описал java.lang.reflect функциональность.

Provides classes and interfaces for obtaining reflective information about classes and objects. Reflection allows programmatic access to information about the fields, methods and constructors of loaded classes, and the use reflected fields, methods, and constructors to operate on their underlying counterparts on objects, within security restrictions.

dimag
()
Ответ на: комментарий от anonymous

>Питон тебе самое то ;)

Меня смущает отсутствие явных операторных скобок :) Я просто не могу читать питоновский код, у меня в глазах всё расплывается :) Ещё смущает его склонность к "специальным" именам вроде __govna_piroga__. Вот такое "отображение" операторов на спецметоды меня настораживает. В первую очередь, это не прибавляет эстетики.

AsphyX ★★★
()
Ответ на: комментарий от ero-sennin

>Это питон и есть. :)

Но в питоне есть, имхо, есть классы как формальный тип :) А я хочу примерно следующего (синтаксис абстракный, только чтобы объяснить):

method_1(...) {
...
}

obj1_new() {
obj1_new["method_1"] = method_1;
obj1_new["method_2"] = { ... }; // типа inline :)
...
}

obj2_new() {
obj2_new = obj1_new();
obj2_new["method_2"] = { ... }; // переопределили
obj2_new["method_3"] = { ... }; // добавили
}

и т.п.

AsphyX ★★★
()
Ответ на: комментарий от AsphyX

>Но в питоне есть, имхо, есть классы как формальный тип :) А я хочу примерно следующего (синтаксис абстракный, только чтобы объяснить):

JavaScript?

dimag
()

Метаклассы - это очень глубокая материя, о которой 99% пользователей даже не нужно задумываться. Если вы не понимаете, зачем они вам нужны – значит, они вам не нужны (люди, которым они на самом деле требуются, точно знают, что они им нужны, и им не нужно объяснять - почему). - Тим Питерс (Tim Peters), гуру по Python

причисляю себя к 99%

alt0v14 ★★★
()
Ответ на: комментарий от AsphyX

> А есть какой-нибудь язык, где классов как абстрактного типа не было бы вовсе, а были бы некие функции-конструкторы, возвращающие некую разновидность хэш-таблицы со ссылками на методы?

Lua

Хотя, как подсказывают товарищи с мест, это всё можно заделать и в Python, и в Ruby, и в JavaScript

yk4ever
()
Ответ на: комментарий от lefsha

> Вообще то говоря строго в Питоне нет никаких классов. Хотя бы на том основании что любая функция или переменная использованная после создания класса может быть его членом. Иначе говоря никакой инкапсуляции данных в классы Питон не предлагает в этой связи само понятие класс теряет смысл.

Ну это у вас предрассудки, на самом деле. Питон просто ломает стереотипы. Злобная инкапсуляция на самом деле не нужна, как не нужны {}.

yk4ever
()
Ответ на: комментарий от lefsha

> Вообще то говоря строго в Питоне нет никаких классов. Хотя бы на том основании что любая функция или переменная использованная после создания класса может быть его членом. Иначе говоря никакой инкапсуляции данных в классы Питон не предлагает в этой связи само понятие класс теряет смысл.

Диагноз: вас перекормили C++ в институте. У нас скоро во всех высокоуровневых языках любая функция сможет стать членом любого класса или методом объекта ;)

> Любой класс или объект должен обладать определёнными свойствами. Добавление свойств и действий на ходу убивает весь изначальный смысл.

А что делать, если посмотрели и поняли, что свойства мало? Не хочешь - не добавляй. Ж)

sv75 ★★★★★
()
Ответ на: комментарий от AsphyX

Это то что ты хочешь???:

def method1():
    print "method 1 executed"

class class1:
    pass

obj1_new=class1() # сделали объект
obj1_new.method1=method1 # на лету добавили метод
obj1_new.method2=lambda x: x*2 # и еще один

obj1_new.method1() # выведет текс "method 1 executed"
print obj1_new.method2(2) # выведет 4

class class2:
    def method2(self,x):
        return x*3

list_of_objects=[obj1_new,class2(),class2()] # список разных объектов (без общего предка)

for i in list_of_objects:
    print i.method2(10)

zhiltsov
()
Ответ на: комментарий от tailgunner

> Чем Луа настолько лучше?

чем питон

anonymous
()
Ответ на: комментарий от tailgunner

> Чем Луа настолько лучше?

Элегантностью и простотой синтаксиса, качеством кода, скоростью и размерами виртуальной машины. Основные преимущества Питона по сравнению с Луа - большая популярность, большее количество уже написанных библиотек.

anonymous
()
Ответ на: комментарий от ero-sennin

>> Кто сможет мне человеческим языком объяснить, что такое аспектно-ориентированное программирование, тому пряник.
Ну я тогда попробую :)
К примеру, есть определённое количество функций (методов), к которые надо "обнять" специальным кодом. Например, вокруг каждой ф-ции из класса А, название которой содержит слово Money, а также для каждой protected ф-ции из класса Б, ив довеску, для каждого конструктора для класса из пакета В, где 2ой параметер является строкой. Вообщжм, нам бы хотелось обнять вызов каждого из них таким кодом который логит параметры вызова, возвращаемое значение, и если было исклюшение, то и его. Это есть logging aspect. Кроме него ещё часто приводится в пример metrics aspect, security aspect ну и сами придумайте чего-нибудь. Для данной операции нужно описать сам аспект и описать паттерн как его применять. Удобство в том, что всё это сконцентрированно в одном месте и если в дальнейшем будет необходимость что-то изменить или просто убрать, то проведя операцию в одном месте, можно получить 100% гарантию от аспектного компилятора, что изменения будут применены действительно везде. Естественно, (интерцепторы) аспекты можно строить в цепочки. Интерцептор, это тип аспекта, выше описанный - когда один код обнимает другой. Есть и другие типы аспектов, но интерцепторы - самые наглядные из них. Так вот, можно, имея метрикс и логгинг интерцепторы, указат, чтобы сначала применялся один, затем другой. При этом код, к которому это будет применяться, для програмиста будет абсолютно чист. То есть можно просто писать логику поведения программы, не забивая голову сецуриты, логами, мерилками, ведь их мозхно прикрутить декларативно, ибо аспецты получаются вообще как внешняя кросс-проэктная библиотека. Более сложный интерцептор - transaction demarcation interceptor. Идея простая - при вызове метода какого-то объекта (по идее, инкапсулируещего бизнес логику), запускается трансакция. Если этот объект вызывает другие методы, то они все исполняются как та же самая трансакция. Как только исполнение покидает 1ый метод в цепочке, то в зависимости от типа выхода трансакция завершается. Например, если выхор был с исключениям, то rollback, а так commit. Ето так, в кратце :) Доков по этой теме много, особенно в мире java. Среди них много толковых введений. Ещё конечно стоит обратить внимание на то, что есть runtime аспекты (spring, hivemind 3> ), а есть compile time. Последние по возможностям сильно отличаются. Например, можно написать аспект, который просто остановит компиляцию, если к private полю будет производится обращение не через gette/setter. Вообщем, тут уже главное НЕ перефантазировать :) Надеюсь, что хоть немного помог


alebu
()

А почему я должен сосредотачиваться на объекте? Это противоестественно. Даже категории созданы для нормального отображения, не говоря уже о жизни. Будем ждать пока поколение ООПешников не вымрет. Ну и поможем чем сможем.

anonymous
()
Ответ на: комментарий от AsphyX

> Но в питоне есть, имхо, есть классы как формальный тип :)

Да, есть классы. А есть инстансы.
Класс, грубо говоря, задает начальные свойства/поведение объекта, но всё это может быть переопределено.
Это, например, прикольно для "ленивого программирования" - когда какие-то свойства вычисляются не заранее, а когда к ним обратятся. 
А при следующем обращении

class Foo:
    classvar1='bebe'
    @property
    def lazyvar1(self):
        # декоратор property позволяет обращаться к методу
        # объекта как к свойству.(без круглых скобок:)
        print 'i will calculate my value and rewrite myself with it; next time you will not see this messsage'
        setattr(self,'lazyvar1', 2+2)
        return self.lazyvar1

obj=Foo()

Свойства нашего объекта:
In [87]: dir(obj)
Out[87]: ['__doc__', '__module__', 'classvar1', 'lazyvar1']

In [88]: obj.lazyvar1
i will calculate my value and rewrite myself with it; next time you will not see this messsage
Out[88]: 4

In [89]: obj.lazyvar1
Out[89]: 4


> А я хочу примерно следующего (синтаксис абстракный, только чтобы объяснить)

ок давайте добавим метод снаружи
In [95]: def bebe():
    print 'i am alive:)'

In [97]: obj.method1=bebe

In [98]: obj.method1()
i am alive:)

In [101]: obj.method2=lambda: [
    sys.stdout.write('i am alive too \n'),
    ('-z' in sys.argv) and sys.stdout.write('i was called with -z command-line parameter \n') or sys.stdout.write('no -z param given\n'),
    'i am result:)'
][-1]

In [106]:

In [106]: obj.method2()
i am alive too
no -z param given
Out[106]: 'i am result:)'

Кстати вот вам и скобки - можно писать так:
(foo(123),bar(321),
foobar(123321))
или так:
[ foo(123),bar(321),
foobar(123321) ]
или как-нить так:

In [119]: print [os.path.splitext(filename)[1] for filename in os.listdir('./') if not filename.endswith('py')]
['', '', '', '.js', '', '', '', '.pyc', '.pyc', '', '', '.pyc', '', '', '', '', '.xml', '', '.cfg', '.pyc', '.js', '', '', '', '.pyc', '.js', '', '.html', '', '.js', '', '.html', '.pyc', '.hg', '.pyc', '', '.pyc', '', '.pyc', '']

In [120]: print [os.path.splitext(filename)[1] for filename in os.listdir('./') if filename.endswith('py')]
['.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py', '.py']


Самое прикольное, что там можно писать в любом стиле. и комбинировать разные парадигмы.


А вот в яваскрипте кстати действительно такого понятия как класс нету-все объекты динамические(кроме встроенных).

pawnhearts ★★★★★
()

Чем дальше, тем всё больше убеждаюсь в том, что Python -- чудесный язык, один из лучших. Вот бы ему добавить форматирование операторными скобками вместо отступов, поддержку регулярных выражений на уровне синтаксиса (как в Perl) и значок перед именами переменных ("$" и т.п., как в shell) -- и всё, получим настолько идеальный язык, что даже не будет нужен Perl.

VladimirP ★★★★
()
Ответ на: комментарий от pawnhearts

P.S. dir(obj) после этих действий будет:
['__doc__', '__module__', 'classvar1', 'lazyvar1','method1','method2']

pawnhearts ★★★★★
()
Ответ на: комментарий от anonymous

>> Чем Луа настолько лучше?
>Элегантностью и простотой синтаксиса, качеством кода, скоростью и >размерами виртуальной машины.

Луа хорош тем что он простой и маленький, поэтому его и любят использовать для простых скриптов встраивыемых в приложения(в основном игры).
( Скорость зависит от того что вы делаете и как вы делаете. )

>Основные преимущества Питона по сравнению с Луа - большая популярность, большее количество уже написанных библиотек.

А также скоростью работы, элегантностью(в луа по-умолчанию необъявленные локальные переменные попадают в глобальный namespace - что весьма опасно, если вы пишете не hello world), возможностью "напрямую" обращаться к двоичным сишными библиотекам и т.д. и т.п.

Подробнее: http://lua-users.org/wiki/LuaVersusPython

pawnhearts ★★★★★
()
Ответ на: комментарий от VladimirP

>Чем дальше, тем всё больше убеждаюсь в том, что Python -- чудесный язык, один из лучших. Вот бы ему добавить форматирование операторными скобками вместо отступов, поддержку регулярных выражений на уровне синтаксиса (как в Perl) и значок перед именами переменных ("$" и т.п., как в shell) -- и всё, получим настолько идеальный язык, что даже не будет нужен Perl.

Ага, настолько хорош, что давайте его изуродуем, убрав мегафичу №1 и добавив идиотский костыль.

vsemnazlo
()
Ответ на: комментарий от anonymous

>> Чем Луа настолько лучше?

> Элегантностью и простотой синтаксиса, качеством кода, скоростью и размерами виртуальной машины.

Стоп-стоп! А в питоне что, неэлегантный синтаксис? Непростой? Априори низкое качество кода и скорость? А размеры машины... да кто их сейчас меряет, эти килобайты! :)

anonymous
()
Ответ на: комментарий от ero-sennin

> Это питон и есть. :) Ну или ECMAScript, он ещё больше на это описание похож.

И Лисп тоже.

eugine_kosenko ★★★
()
Ответ на: комментарий от VladimirP

Не трогайте отступы. 
Отступы это гениально - теперь чужой код можно читать и читать легко.

Смотрите какой кошмар с скобками:

function SendChangesToServer(st,rec,op){
	if (op!=Ext.data.Record.EDIT)
		{
		 Ext.Ajax.request({
		   url: '/{{site_root}}/ajax_order_lineedit/',
		   success: onEditCountSuccess,
		   failure: onEditCountUnsuccess,
		   params: { recid:  rec.get('posid'),count:rec.get('count'),gridid: rec.id},
		   options:rec
		 });
                 rec.set('summ',rec.get('count')*rec.get('price'));
		}
        else if (op!=Ext.data.Record.COMMIT){ rec.commit(); };
};

И насколько красивее с отступами:
def SendChangesToServer(st,rec,op):{
    if (op!=Ext.data.Record.EDIT):
       Ext.Ajax.request(url: '/{{site_root}}/ajax_order_lineedit/',\
                        success: onEditCountSuccess,\
                        failure: onEditCountUnsuccess,\
 		        params: { recid: rec.get('posid'),\
                                  count:rec.get('count'),\
                                  gridid: rec.id},\
                        options:rec});
       rec.set('summ',rec.get('count')*rec.get('price'));
    elif(op!=Ext.data.Record.COMMIT):
        rec.commit(); 

demmsnt
()
Ответ на: комментарий от demmsnt

А с скобками одних стилей будет:

func name() {однаблин длинаая строка из обфускатора}

func name() {
JS стиль пишу как хочу и
вообще нихрена отступов нет
10 функций подряд и 
вообще не видно где, что началось
, а еще 10 if там и будет вообще
{
}
{{
asdasd}}
однаблин длинаая строка из обфускатора}

func name() 
{
непонятно псевдопаскальный стиль
   10 функций подряд и 
   вообще не видно где, что началось
, а еще 10 if там и будет вообще
10 функций подряд и 
вообще не видно где, что началось
, а еще 10 if там и будет вообще
}


func name() 
     {
     стиль имитирующий питон
     if () 
        {
         только всеравно пробелы едут
         и скобки сожрали 
         кучу строк
         }
     }

demmsnt
()
Ответ на: комментарий от alebu

> Ну я тогда попробую :)

Спасибо, прояснилось. А то сколько ни читал википедию, мозг тут же аварийно отключался из-за перегрузки энтерпрайз-баззвордами.

ero-sennin ★★
()
Ответ на: комментарий от pawnhearts

> А также скоростью работы

Луа быстрее Питона.

> элегантностью

Синтаксис Питона чувствителен к форматированию. Это называется "элегантность"?

> (в луа по-умолчанию необъявленные локальные переменные попадают в глобальный namespace - что весьма опасно, если вы пишете не hello world)

Это кажется опасным, но это не опасно. Все новички в Луа начинают с закрытия global scope через метатаблицы, но быстро отказываются от этого.

Кроме того, в Луа всего одна действительно глобальная переменная - _G.

> Подробнее: http://lua-users.org/wiki/LuaVersusPython

Я пишу на обоих языках, на Луа много, на Питоне уже нет.

anonymous
()
Ответ на: комментарий от anonymous

> Стоп-стоп! А в питоне что, неэлегантный синтаксис? Непростой? Априори низкое качество кода и скорость?

Элегантный (если Вы считаете элегантной зависимость смысла программы от расстановки пробелов), простой, с высоким качеством кода и скоростью.

Просто Луа элегантнее, проще и быстрее. Оба языка хороши. Но Луа лучше.

> А размеры машины... да кто их сейчас меряет, эти килобайты! :)

Виндузятники на ЛОРе?! :)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.