Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 26, 2008 17:03:43

balu
От:
Зарегистрирован: 2006-05-24
Сообщения: 521
Репутация: +  0  -
Профиль   Отправить e-mail  

Что можно написать на Python?

Андрей Светлов
все равно требуется постоянно следить за архитектурой и писать тесты. Не делаешь этого - копаешь себе яму. Особенно если разработчиков много.
да. Но не всегда можно предугадать все варианты типов, которые могут быть переданы в реальной работе. Впрочем, тогда и в строготипизированных ЯП возникнет ругань.



Отредактировано (Дек. 26, 2008 17:10:24)

Офлайн

#2 Дек. 26, 2008 17:58:42

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Что можно написать на Python?

Я для интерфейсов делаю классы-хранилища с проверкой типов.



Офлайн

#3 Дек. 26, 2008 18:03:59

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Что можно написать на Python?

У меня такой потребности не возникало, но интересно - как делаете строгую типизацию где надо? Небольшой пример бы, для иллюстрации.
Спасибо.

Офлайн

#4 Дек. 26, 2008 18:56:03

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Что можно написать на Python?

Я для себя использую примерно такой вариант. Знаю, что он не идеален, но мне пока хватает.

# -*- coding: UTF-8 -*-

class BaseIface(object):
'''
базовый класс, с проверкой имени кладомой в него переменной и ее типа
'''
def __setattr__(self, name, value):
if not name in self.right_vars: #проверяем, что такое имя разрешено
raise ValueError, ('bad variable name')
elif not isinstance(value, self.right_vars[name]): #поверяем, что такой тип разрешен
raise ValueError, ('bad variable type')
else:
object.__setattr__(self, name, value) #если все ок - кладем =)


class PriceField(BaseIface):
'''
интерфейсный класс
'''
right_vars = { #список разрешенных переменных с указанием их типов.
'price': float,
'name': unicode
}


class PriceFieldDef(BaseIface):
'''
другой интерфейсный класс
'''
right_vars = { #список разрешенных переменных с указанием их типов.
'price': float,
'name': unicode
}

#можно забить значение по умолчанию
def __init__(self):
self.price = 0.0
self.name = u''


f = PriceField()

f.price = 3.0
f.name = u'test'

f1 = PriceFieldDef()
print f1.price

#f.price = 1 #ошибка
#f.prise = 1.0 #ошибка
Использую это для обмена даными между разными блоками программы =)



Отредактировано (Дек. 26, 2008 19:07:04)

Офлайн

#5 Дек. 26, 2008 19:32:54

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

Что можно написать на Python?

Типизированные атрибуты

>>> class typed_attr(object):
... def __init__(self, name, type):
... self.name = name
... self.type = type
... def __set__(self, inst, value):
... assert isinstance(value, self.type)
... setattr(inst, '_typed_'+self.name, value)
... def __get__(self, inst, owner):
... assert inst is not None
... return getattr(inst, '_typed_'+self.name)
...
>>> class A(object):
... a = typed_attr('a', int)
...
>>> a = A()
>>> a.a = 34
>>> a.a
34
>>> a.a = 'abc'
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "<interactive input>", line 6, in __set__
AssertionError
>>>
При использовании peak.decorators можно избежать самоцитирования при создании свойства и вычислять имя атрибута после создания дескриптора. Того же эффекта можно добиться создав метакласс для всех пользовательских типов. Но это уже детали.

Для проверки аргументов/вычисляемого значения подойдут тривиальные декораторы. Можно их сделать очень быстрыми (снижаем накладные расходы на обвязку), при этом возможная сложность декораторов мало волнует - весь люд воспринимает их как “магию”. Примерно так же мало кто задумывается, как именно реализованы некоторые нетривиальные питоновские builtins и itertools. Дока есть - и ладно.
Очень хочу порекомендовать статью Сергея Щетинина, посвященную как раз этому.

P.S. Да, всем этим стоит заниматься исключительно в публичных интерфейсах. Интимные детали подсистем в проверке типов н нуждаются. Требуется именно защита от дурака (программиста из другого отдела), который всего лишь хочет быстро вызывать вашу API и не вникать в детали реализации. Если API очень прост и не допускает разночтений - опять же проверку типов опускаем за ненадобностью. У нас она “отключена по умолчанию” - ничего лишнего. Но когда часто начинаем “спотыкаться” или просто чувствуем “проблемное место” - вводим.



Отредактировано (Дек. 26, 2008 19:39:01)

Офлайн

#6 Дек. 26, 2008 19:44:11

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Что можно написать на Python?

Андрей Светлов
Интимные детали подсистем в проверке типов н нуждаются. Требуется именно защита от дурака (программиста из другого отдела), который всего лишь хочет быстро вызывать вашу API и не вникать в детали реализации.
Поддреживаю.
Андрей Светлов
Если API очень прост и не допускает разночтений - опять же проверку типов опускаем за ненадобностью.
Не совсем согласен, иногда бывают глупые опечатки, от которых спасет такая проверка.



Офлайн

#7 Дек. 26, 2008 19:46:21

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Что можно написать на Python?

Спасибо, весьма интересно.

Офлайн

#8 Дек. 26, 2008 21:06:26

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

Что можно написать на Python?

Еще не могу удержаться:
- хорошая система исключений.
- Во первых, информативный текст. В примере я бросал простой assert. По хорошему нужно приложить к нему второй параметр. Что-то вроде
assert isinstance(value, self.type), ‘Attribute %r must be instance of %r type, got %r’%(self.name, setlf.type, type(value))
Очень облегчает анализ ошибки
- Во вторых, никогда не ловите и не бросайте Exception. except Exception съест в том числе и непредвиденные ошибки - NameError например. Если не знаете тип исключения - RuntimeError был сделан как раз для вас.
- Если ловите, скажем, ValidationError на save и хотите превратить его в TransactionError - сделайте так, чтобы ваш TransactionError мог рассказать о вложенном исключении, которое это проблему вызвало. Вложеные тип, значение и, главное, stack trace. Опять же поможет.
- логирование.
- Модуль logging хорошо - всегда его используйте. Имейте много логеров. Год назад накропал статейку Пользуюсь практически без изменений - разве что по рекомендации Макса Ищенко добавил mod_logger. В девелоперской конфигурации обязательно логируйте помимо всего прочего на консоль. В production - обязательно в файл. Его вам хотя бы по email перешлют. Файлы ротировать и сохранять достаточно долгое время. Чтобы на тот момент, когда вам клиент нажалуется - у него логи все еще были.
- принты не используйте. Сам их часто вставляю - но только для отладки. В svn они не попадают. Хотели даже pre-commit hook вставить, который питоновские файлы бы парсил и если увидел незакомментареный print - commit бы не допускал. Руки не доходят, по простому незлым тихим словом поддерживаем порядок.
- repr. Очень полезная штука. Практически у каждого класса должен быть свой переопределенный __repr__. Который нормально описывает класс. Например, для пресловутого объекта из БД по имени “пользователь” возвращается строка <User ‘vpupkin@gmai.com’> если email - уникальный индекс. Опять же сокращает отладку. Обратите внимание, что email в кавычках - стандартная реализация repr для строки. Позволяет наглядно показать, есть ли в параметре пробелы или таки нет. Тоже сохраняет время. repr вызывается при ‘%r’%arg, а при ‘%s’%arg зовется str - который может иметь (и зачастую так и есть) совершенно другую реализацию. При логировани и бросании исключений используйте именно repr. Экономит время, особенно когда паренек из support team подходит с вопросом - а почему у клиента не работает. У этого паренька иногда тоже воспроизводится - если он на том же environment смог поймать проблему. Но нет отладчика. Исходников по умолчанию тоже нет. Перенастроить мое девелоперское окружение на то, что вертится у заказчика - пара часов работы в лучшем случае. В худшем - сутки (и это при том, что заказчики сидят в своем интранет, к которому мы имеем достаточно свободный доступ - просто чудеса). Зато есть логи. Чем они информативней (молчат о стандартных ситуациях и подробно рассказывают о возникшей проблеме - тем быстрее она решается)

- это позволяет свести отладку к минимуму. Да, я сам тоже ей пользуюсь. import pdb;pdb.set_trace() Получаю вполне приличную питоновскую консоль в проблемном месте. Все, что я прошу у системы - информативное (помните про repr). Отлаживать долго не нужно. Чаще нужно именно войти питоном куда следует и поспрашивать. Стек, окружение, то-се. Не нужно трассировать глубокие стеки вызовов - логи скажут. После вырабатывания привычки к подобному стилю здорово экономишь свое время. Как и привычка к написанию юниттестов спасает от часов тупой отладки.

- Ключевое слово - привычка. Привык, и пишу мало кода, который делает много дела. Привык - и затягиваю сдачу истории до тех пор, пока она не будет готова с моей точки зрения. В результате разработка получается сбалансированной и быстрой.
Привык - и выдаю всегда только хороший (по крайней мере с моей точки зрения) код.

P.S. Конечно, все вышесказанное - только лишь моя точка зрения. Каждый может не согласиться, оспорить или противопоставить свою. С удовольствием выслушаю.

balu
Спасибо за роль хорошего оппонента. Ответы на твои вопросы помогли взглянуть на проблему немного с другой стороны.



Отредактировано (Дек. 26, 2008 21:17:22)

Офлайн

#9 Дек. 27, 2008 22:58:03

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Что можно написать на Python?

Это хорошо, что ты не сдержался :)

Офлайн

#10 Дек. 28, 2008 12:22:32

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Что можно написать на Python?

Ferroman
Это хорошо, что ты не сдержался :)
+1 очень интересно!!!



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version