LINUX.ORG.RU

[Python] __getattr__ с подвывертом

 


0

0

Есть некий класс, все атрибуты у которого незадекларированы в явном виде, но для которого определен __getattr__(). Нужно этот __getattr__() реализовать так, чтобы можно было сказать

someattr = ClassName.foo

и возвращалось значение одного типа, но если сказать

instance = ClassName()
someattr = instance.foo

возвращалось значение совершенно другого типа.

Что мне надо дочитать, чтобы реализовать такой класс?

★★★★★

Что-нибудь о метаклассах, ИМХО.

P.S. подвыподвертом

P.P.S. я бы тебя уволил за такие трюки.

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

Это мой личный проект — как хочу, так и фигачу. А для того, чтобы сделать _именно_так_, у меня причин есть с три короба.

Про метаклассы читал, пока что в цельную картину не особо укладывается. То бишь понимаю общую идею, но не особо понимаю, как сделать метод класса статическим, а тот же метод, но у объекта, обычным.

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

> То бишь понимаю общую идею, но не особо понимаю, как сделать метод класса статическим

Один из нас не понимает общую идею. В приведенном тобой примере нет "статического" метода. Первый foo - метод, определенный в метаклассе, второй - в классе. Как-то так, хотя я и сам не разбирался глубоко в этой магии.

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

Короче, под вечер попробую — отпишусь с примером и зачем это нужно.

Стандартная дока по метаклассам и классам нового стиля (2.2+) описывает магию намного более черную, а простые примеры идут нафиг.

shimon ★★★★★
() автор топика

Дескрипторы в помощь

class Foo(object):
    def __get__(self, instance, owner):
        if instance:
            return 100
        else:
            return '50'

class A(object):
    pass

A.foo = Foo()

print 'A.foo:', A.foo
print 'A().foo:', A().foo
baverman ★★★
()
Ответ на: комментарий от shimon

Ты хоть расскажи, откуда берется мысль сделать такое чудо -- разные типы (правда интересно, т.к. мои мысли на 99.9% укладываются в статическую типизацию).

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

Допустим, у меня какой-то зреет ORM. И надо написать так:

collection = EntityCollection.find(Entity.someField > 10)

на самом деле выражение должно выдать не булевский тип, а объект, который потом [с другими такими же] оттранслируется во фрагмент SQL.

С другой стороны, когда find() отработает, я получу в collection список объектов Entity. И вот тогда я хочу иметь возможность делать вещи типа:

for i in collection:
  print "someField is %d" % (i.someField) # а здесь уже настоящее целое
  b = i.someField < 30 # здесь сравнение в Python с булевским результатом

Для unbound objects возвращается полуфабрикат, для bound objects фактическое значение.

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

ИМХО интересная идея, и подводных камней я не вижу (если предположить, что в случае, когда someField будет атрибутом класса, выражение Entity.someField > 10 будут сразу вычисляться, а не транслироваться в SQL). Disclamer: с питоном и стилем программирования на нем не знаком.

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

> (если предположить, что в случае, когда someField будет атрибутом класса, выражение Entity.someField > 10 будут сразу вычисляться, а не транслироваться в SQL)

Ненене, Дэвид Блейн. Вычисляться будут только тогда, когда bound objects -- типа когда Entity().someField, а не Entity.someField (типа "статически").

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

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

А ты уверен, что никому не захочется в дополнение к фиктивным атрибутам класса, предназначенных для генерации СКЛ, сделать один-два настоящих?

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

> А ты уверен, что никому не захочется в дополнение к фиктивным атрибутам класса, предназначенных для генерации СКЛ, сделать один-два настоящих?

Начнем с того, что в питоне, скажем так, есть разница между атрибутами самого класса и атрибутами экземпляра класса. Мне сперва это тоже слабо укладывалось в голову. Вполне можно сделать так, что атрибуты суть что угодно, необязательно дескрипторы. (Дескрипторами можно начинить из метакласса родительский класс, а в потомке доопределять что душеньке угодно.)

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

> Допустим, у меня какой-то зреет ORM.

> на самом деле выражение должно выдать не булевский тип, а объект, который потом [с другими такими же] оттранслируется во фрагмент SQL.

Переизобретаете sqlalchemy? Если до рабочего состояния дойдёт, выложите, будьте добры. Очень интересуют поиски в направлении "правильного" ORM :)

Нынче глаза ломаю об выражения sqlalchemy. Идея вроде неплохая, но выглядит всё это жутко. Ещё посмотрим как работает...

ЗЫ: таки сырой SQL лучше всего годится для сложных запросов, как ни крути.

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

ЗЫ: таки сырой SQL лучше всего годится для сложных запросов, как ни крути.

Я знаю об этом. У меня задача на самом деле научить это дело танцевать с Twisted, то бишь поддержка Deferred'ов из коробки, а то Storm — с костылями, SQLalchemy — тоже с костылями, Axiom только со SQLite. Хочешь постгрес, а оно ни в какую.

Если до рабочего состояния дойдёт, выложите, будьте добры.

На гуглокоде место застолбил уже, чтобы было. Ну и пинайте иногда, помогает. ;-)

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

Хм. Хороший вопрос. Но, по-моему, оно внутри себя должно алиасы раздавать и неоднозначности решать... Иначе нафиг надо?

Кроме того, у меня такое чувство, что лучше древовидность хранить во вспомогательной таблице, на одном проекте мы этого не делали, а сейчас огребаем во все щели.

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

меня в этом проекте интересует метапрограммирование, а не готовый проект (и вообще говоря, я не верю в языки с дин. типизацией)

> Хм. Хороший вопрос. Но, по-моему, оно внутри себя должно алиасы раздавать и неоднозначности решать... Иначе нафиг надо?

вопрос в том, как ты это *запишешь*, ибо entity_collection.find(Entity.child==Entity.parent) не прокатывает

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

> вопрос в том, как ты это *запишешь*, ибо entity_collection.find(Entity.child==Entity.parent) не прокатывает

Это почему не прокатывает? Операция равенства также перегружается как и все остальные.

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

потому, что нам надо что-то типа entity_collection.find(THIS.Entity.child==THAT.Entity.parent)

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