python (питон)

Description: Программирование на супер модном мега крутом языке Питон.

dyvniy M
Topic author, Администратор
Администратор
Avatar
dyvniy M
Topic author, Администратор
Администратор
Age: 39
Reputation: 1
Loyalty: 1
Posts: 3472
Joined: Wed, 10 Oct 2012
With us: 9 years 3 months
Профессия: Программист
Location: Россия, Москва
ICQ Website Skype VK

#25by dyvniy » Tue, 24 Mar 2015, 10:33:35

Информация о поиске модулей.

Code: Select all

import sys
sys.path.append('PyQt4')
sys.path.append('PyQt4/wig')
print sys.path
Когда вы импортируете модуль, то Питон ищет файл с таким именем не где-нибудь, а в определённых каталогах. Эти каталоги определены в переменной окружения PYTHONPATH вашей операционной системы. Эта переменная имеет структуру, схожую с переменной PATH и так же содержит в себе каталоги, где Питон будет искать модули. При отсутствии этой переменной, Питон будет искать модули в папке, куда были установлены его исполняемые файлы, а так как этот каталог зависит от инсталляции и частенько никаких модулей в нём нет, то удалять или изменять без особой необходимости PYTHONPATH не следует. Доступ к списку каталогов поиска можно получить также из списка sys.path модуля sys(import sys). Этот список можно изменять программно, путём стандартных операций со списками. Ни в коем случае не называйте свои модули так же, как названы стандартные модули Питона, так как это повлечёт за собой труднообнаружимую ошибку. Если подлежащий импорту скрипт находится в том же каталоге, что и вызывающая его программа, то нет необходимости обращаться к sys.path, так как Питон ищет модули также и в текущей директории.
http://citforum.ru/programming/python/python3.shtml
Image

dyvniy M
Topic author, Администратор
Администратор
Avatar
dyvniy M
Topic author, Администратор
Администратор
Age: 39
Reputation: 1
Loyalty: 1
Posts: 3472
Joined: Wed, 10 Oct 2012
With us: 9 years 3 months
Профессия: Программист
Location: Россия, Москва
ICQ Website Skype VK

#26by dyvniy » Tue, 28 Apr 2015, 10:55:17

Питон и джанга сервер на дебиане
http://www.fullautomatic.ru/index.php/debian-ubuntu-rhel-centos/241-93
Image

dyvniy M
Topic author, Администратор
Администратор
Avatar
dyvniy M
Topic author, Администратор
Администратор
Age: 39
Reputation: 1
Loyalty: 1
Posts: 3472
Joined: Wed, 10 Oct 2012
With us: 9 years 3 months
Профессия: Программист
Location: Россия, Москва
ICQ Website Skype VK

#27by dyvniy » Fri, 23 Oct 2015, 18:15:58

пайпы в питоне
http://habrahabr.ru/post/117679/
Spoiler
Пайпы, the pythonic way
Python*
Одни питонисты любят код читаемый, другие предпочитают лаконичный. К сожалению, баланс между первым и вторым — решения по-настоящему изящные — редко случается встретить на практике. Чаще стречаются строки вроде
my_function(sum(filter(lambda x: x % 3 == 1, [x for x in range(100)])))
Или четверостишья а ля
xs = [x for x in range(100)]
xs_filtered = filter(lambda x: x % 3 == 1, xs)
xs_sum = sum(xs_filtered)
result = my_function(xs_sum)
Идеалистам же хотелось бы писать как-то так
result = [x for x in range(100)] \
| where(lambda x: x % 3 == 1)) \
| sum \
| my_function

Не в Питоне?

Простую реализацию подобных цепочек не так давно предложил некий Julien Palard в своей библиотеке Pipe.

Начнем сразу с примера:
from pipe import *
[1,2,3,4] | where(lambda x: x<=2)
#<generator object <genexpr> at 0x88231e4>

Упс, интуитивный порыв не прокатил. Пайп возвращает генератор, значения из которого еще только предстоит извлечь.
[1,2,3,4] | where(lambda x: x<=2) | as_list
#[1, 2]

Можно было бы вытащить значения из генератора встроенной функцией приведения типа list(), но автор инструмента был последователен в своих изысканиях и предложил нам функцию-пайп as_list.

Как видим, источником данных для пайпов в примере стал простой список. Вообще же говоря, использовать можно любые итерируемые (iterable) сущности Питона. Скажем, «пары» (tuples) или, что уже интересней, те же генераторы:
def fib():
u"""
Генератор чисел Фибоначчи
"""
a, b = 0, 1
while 1:
yield a
a, b = b, a + b

fib() | take_while(lambda x: x<10) | as_list
#0
#1
#1
#2
#3
#5
#8
Отсюда можно извлечь несколько уроков:
в пайпах можно использовать списки, «пары», генераторы — любые iterables.
результатом объединения генераторов в цепочки станет генератор.
без явного требования (приведения типа или же специального пайпа) пайпинг является «ленивым» в том смысле, что цепочка есть генератор и может служить бесконечным источником данных.

Разумеется, радость была бы неполной, не будь у нас легкой возможностисоздавать собственные пайпы. Пример:
@Pipe
def custom_add(x):
return sum(x)
[1,2,3,4] | custom_add
#10
Аргументы? Легко:
@Pipe
def sum_head(x, number_to_sum=2):
acc = 0
return sum(x[:number_to_sum])
[1,2,3,4] | sum_head(3)
#6
Автор любезно предоставил достаточно много заготовленных пайпов. Некоторые из них:
count — пересчитать число элементов входящего iterable
take(n) — извлекает из входного iterable первые n элементов.
tail(n) — извлекает последние n элементов.
skip(n) — пропускает n первых элементов.
all(pred) — возвращает True, если все элементы iterable удовлетворяют предикату pred.
any(pred) — возвращает True, если хотя бы один элемент iterable удовлетворяют предикату pred.
as_list/as_dist — приводит iterable к списку/словарю, если такое преобразование возможно.
permutations(r=None) — составляет все возможные сочетания r элементов входного iterable. Если r не определено, то r принимается за len(iterable).
stdout — вывести в стандартный поток iterable целиком после приведения к строке.
tee — вывести элемент iterable в стандартный поток и передать для дальнешей обработки.
select(selector) — передать для дальнейшей обработки элементы iterable, после применения к ним функции selector.
where(predicate) — передать для дальнейшей обработки элементы iterable, удовлетворяющие предикату predicate.
А вот эти поинтересней:
netcat(host, port) — для каждого элемента iterable открыть сокет, передать сам элемент (разумеется, string), передать для дальнейшей обработки ответ хоста.
netwrite(host, port) — то же самое, только не читать из сокета после отправления данных.
Эти и другие пайпы для сортировки, обхода и обработки потока данных входят по умолчанию в сам модуль, благо создавать их действительно легко.
Под капотом декоратора Pipe

Честно говоря, удивительно было увидеть, насколько лаконичен базовый код модуля! Судите сами:
class Pipe:

def __init__(self, function):
self.function = function

def __ror__(self, other):
return self.function(other)

def __call__(self, *args, **kwargs):
return Pipe(lambda x: self.function(x, *args, **kwargs))
Вот и все, собственно. Обычный класс-декоратор.

В конструкторе декоратор сохраняет декорируемую функцию, превращая ее в объект класса Pipe.

Если пайп вызывается методом __call__ — возвращается новый пайп функции с заданными аргументами.

Главная тонкость — метод __ror__. Это инвертированный оператор, аналог оператора «или» (__or__), который вызывается у правого операнда с левым операндом в качестве аргумента.

Получается, что вычисление цепочки начинается слева направо. Первый элемент передается в качестве аргумента второму; результат вычисления второго — третьему и так далее. Безболезненно проходят по цепочке и генераторы.

На мой взгляд, очень и очень элегантно.

Послесловие

Синтаксис у такого рода пайпов действительно простой и удобный, хотелось бы увидеть что-то подобное в популярных фреймворках; скажем, для обработки потоков данных; или — в декларативной форме — выстраивания в цепочки коллбеков.

Единственным недостатком именно реализации являются довольно туманные трейсы ошибок.

О развитии идеи и альтернативных реализация — в следующих статьях.
python, pipes
+79

3405

124


Владимир Казанов @VlK карма187,2 рейтинг0,0
Похожие публикации

10 приложений для изучения Python на Android-устройствах
Удалённое исполнение системных команд по запросу через сокеты на Python 3. Часть 2. Протокол передачи данных (8)
Удалённое исполнение системных команд по запросу через сокеты на Python 3 или как я сайты скачивал (12)
Событийно-ориентированный бэктестинг на Python шаг за шагом. Часть 4
Пишем графическую программу на Python с tkinter (11)
Комментарии (81)

+1 crash18 апреля 2011 в 02:35#
супер
–3 xfather18 апреля 2011 в 02:41#↵↑
Да уж, всё гениальное просто. Но не всё простое гениально)
+5 TheBits18 апреля 2011 в 02:42#
Утрированный пример на самом деле решается так:
my_function(sum(x for x in xrange(100) if x % 3 == 1))

По сравнению с:
[x for x in range(100)] | where(lambda x: x % 3 == 1) | sum | my_function
+2 Amper18 апреля 2011 в 03:38#↵↑
Неправда ваша, было бы так:
range(100) | where(lambda x: x % 3 == 1) | add | my_function
+1 TheBits18 апреля 2011 в 07:16#↵↑
Почему моя, если такой код в статье?
0 Amper18 апреля 2011 в 07:56#↵↑
Действительно… в статье пример какой-то странный…
0 VlK18 апреля 2011 в 13:42#↵↑
пример в статье высосан из пальца, признаюсь. Стоило порыться в рабочем коде и найти что-нибудь эдакое…
+2 mikhanoid18 апреля 2011 в 07:18#↵↑
Пайпы читать проще и редактировать. Даже если они и длиннее выглядят. Поток данных проще: слева направо. А в Вашем примере надо сначала забежать глазами внутрь скобок, потом обратно.
+2 b0n3Z18 апреля 2011 в 10:29#↵↑
total = sum(x for x in range(100) if x % 3 == 1)
result = my_function(total)

Читаемо? Даже очень. Лично я не люблю костыли. Пайпы это хорошо только в баше. И это НЕ pythonic way.
0 mikhanoid18 апреля 2011 в 12:21#↵↑
Ну, а теперь представьте, что нужно связать около 10-ка функций. Будет очень громоздко. А чем перегрузка операторов не pythonic way? Вроде же, это у них там стандартный механизм… Ну. Насколько мне известно…
+5 ingspree18 апреля 2011 в 12:24#↵↑
pythonic — это не значит, что нужно писать, используя все средства языка для достижения цели. Pythonic — это как бы одновременно код должен быть простой, незагрязнëнный и понятный.
+1 mikhanoid18 апреля 2011 в 19:29#↵↑
Ну. Это же не объективные понятия: простой, незагрязнённый и понятный. Кому-то pipe'ы понятнее и проще: зачем я должен придумывать имена временных переменных, если за меня это может сделать библиотека. Это проще, на мой вкус. И тут нет призыва использовать все средства. Используется одно из средств, удобным во многих ситуациях способов. И на самом деле, тут ничего нестандартного и страшного нет, потому что вот этот pipe — вполне себе чуть ограниченная воплощение стандартной концепции монады, которая считается хорошим инструментом программирования.
+2 ingspree18 апреля 2011 в 20:29#↵↑
Ну, кроме того, в питоне не принято абьюзить синтаксис — это принято в хаскеле. Точно так же у меня сейчас в коде рабочего проекта есть реализация стрелок на питоне, которая использует >>. Мало кто выкупает, что и как там происходит. Я б не делал такого ради любви к людям.
+1 xfather18 апреля 2011 в 13:03#↵↑
Есть один момент — обычно, если есть около 10-ка функций идущих подряд, и это независимые функции, а не запрос, как в примере(select… where ...), то при отладке всегда нужно проверить результат каждого промежуточного вызова. И я, лично, вряд ли бы писал сначала по одному:
b=fun1(a)
c=fun2(b)
а в релизном варианте переписывал в виде с = fun1(a) | fun2()
Во-первых долго, во-вторых, мало ли, вдруг потом ещё придется мне, или кому-то другому, отлаживать программу.
0 VlK18 апреля 2011 в 15:14#↵↑
Не надо ничего переписывать. Тестируйте каждый пайп в отдельности, а потом всю цепочку в совокупности. Привет юниттестам! В этом смысле никакой разницы с простыми функциями.

0 Suor18 апреля 2011 в 17:53#↵↑
Это прикольно, но это не python way, это ruby way.
0 mikhanoid18 апреля 2011 в 19:34#↵↑
Чё-то это уже странные утверждения, imho. Если это написано на Python, то какой нафиг Ruby way? По-вашему, что? Вообще никакую библиотеку нельзя использовать, потому что там какие-то функции понаписаны, и никто не поймёт, что происходит, читая код, в котором они используются.

Мда… Фанаты — люди странные. Сделан классный механизм, стандартными средствами их любимого языка… Радоваться надо, разве нет? А то, что какие-то там проблемы могут быть, да… Могут. Но это повод библиотеку развивать, а не трясти перед ней python way'ем.

Эх :( Вы убили во мне желание воспользоваться в следующем проекте Python'ом. Какое-то у него Дао странное. Буду юзать Lua.
+1 ingspree18 апреля 2011 в 20:33#↵↑
Ну какие фанаты, ну что это за разбрасывание лейбами? «Любители метапрограммирования — люди странные. Можно написать так просто, так нет же, дай сделать что-нибудь позапутаннее.»

Я вот сейчас поддерживаю большую довольно кодовую базу на питоне (80к+ SLoC, для питона это — очень много), и надо сказать, что любая попытка внести маленькие приятные штуки оказывается приятной только для автора. Или, другими словами, задолбало находить странные потуги чуваков на метапрограммирование. Хочется оторвать руки и пришить что-то, что будет выдавать поддерживаемый код, а не отрыжки мамонта.

Да, можно и с метапрограммированием писать поддерживаемый код. Вопрос лишь в самодисциплине, конечно. И за значения по умолчанию я принимаю то, что у большинства самодисциплина плоха.
0 VlK19 апреля 2011 в 02:04#↵↑
Метапрограммирование? Это что такое? Декораторы? Метаклассы? Обычная весьма вещь, в любом коде встречается, множество фреймворков это использует.

Тут другой вопрос. Что есть хороший программист? Тот, который, вникая в систему и внося в нее изменения, не нарушает архитектуру и внутренние соглашения.

Что есть великолепный программист? Тот, кто может, усвоив правила большой системы, увеличить внутреннюю корректность, не нарушая цельности.

Что есть плохой программист? Тот, кто использует приемы, идущие в разрез с архитектурой системы; и не принимающий общие решения.

И метапрограммирование не имеет к этому никакого отношения.

0 svetlov20 апреля 2011 в 18:35#↵↑
Я бы сказал, что метапрограммирование — это построение DSL. Внутренних или внешних.
А декораторы-метаклассы — всего лишь детали реализации. Подмножество используемых для метапрограммирования инструментов.
0 VlK21 апреля 2011 в 01:25#↵↑
Вероятно, это прозвучит забавно, но… Разве любое программирование API, уж тем более вблизи парадигмы ООП, — не то ли самое построение DSL?

Метапрограммирование в случае Питона — и не только его самого — это страшное название для простой вещи: изменения в поведении классов, будь то создание экземпляров класс, удаление, использование с операторами. Конечно, с такими вещами следует быть аккуратным. Но не более того!

И вообще буду строгим :). Признаться, после ознакомления с «DSL» на примере Scala, Haskell и Ruby, я перестал понимать, откуда взялась в специальной прессе и блогосфере такая шумиха вокруг этого неопределенного термина; так же посмеиваюсь над теми, кто делает идола из ООП-подхода. Подумаешь, догадались данные складывать в кучку с функциями для работы с ними! Полиморфизм — просто издержки жесткой системы типов; инкапсуляция — просто хорошая практика программирования; наследование — не самый удачный способ менять поведение объектов класса.

И все. :)
0 svetlov21 апреля 2011 в 02:25#↵↑
Лично у меня эти понятия различаются «в голове».
Можно делать ООП на С. А можно и на С++ писать «с классами», но без ООП.
DSL и ООП предполагают несколько отличающийся способ мышления.

Т.е. если я делаю внутренний DSL на Питоне — то использую метаклассы, декораторы, перегрузку операторов. Главное — думаю о получившейся конструкции как о создании нового микроязыка (не выходящего за синтаксис Питона, конечно). Вот и вся разница.
0 VlK21 апреля 2011 в 02:59#↵↑
Но согласитесь, понятия различаются очень условно! Можно даже сказать, что DSL — это просто что-то вроде фразы «надо стремиться говорить на языке целевой области». А уж средства… ООП, функциональный подход, метапрограммирование, макросы (даже в Си/Си++ что-то похожее на DSL с их помощью вытворяют )… Кто во что горазд.

В рамках концепции ООП очень даже можно писать DSL. Скажем, тот же злосчастный джанговский ORM; многие другие реализации ActiveRecord — очень даже себе DSL.

Для меня твердой грани давно уже нет; видать слегка подпортил себе мышление обилием опробованных языков :-) DSL — это просто одна из задач, что иногда встречается.
0 svetlov21 апреля 2011 в 03:17#↵↑
Полностью согласен, различие небольшое.

О метапрограммировании на C++. Не могу удержаться:
www.boost.org/doc/libs/1_46_1/doc/html/xpressive/ ... sive.user_s_guide.introduction
И связка с Питоном:
www.boost.org/doc/libs/1_46_1/libs/python/doc/tutorial/doc/html/python/exposing.html

Это не макросы, все гораздо хуже — шаблоны с частичной специализацией.
0 VlK21 апреля 2011 в 20:37#↵↑
И это при том, что даже некий Александреску уже давно отказался от С++, как слишком проблемного языка :)
0 mikhanoid18 апреля 2011 в 19:42#↵↑
Хм. Особых проблем с отладкой pipe'ов в том же Bash нет. А вот эти Python-пайпы всяко более удобны.
0 svetlov20 апреля 2011 в 18:37#↵↑
Удобны более чем что? Чем непайпы?
В баше проблем нет, потому что нет и многого другого. Перегрузки операторов, например.
0 VlK21 апреля 2011 в 02:01#↵↑
В bash как языке есть множество своих проблем: архаичный синтаксис, много избыточности и бла-бла-бла.

С другой стороны, в bash как инструменте для работы в командной строке есть много плюсов: простота, хорошая работа с текстом. Да и просто обмен данными через stdin/stdout, на мой взгляд — это блестяще. не говоря уже о десятилетиях добрых *никсовых традиций и лучших практик.

Однако, здесь речь идет прежде всего об использовании хорошо знакомого любым программистам синтаксиса для построения схожей абстракции на языке общего назначения…

Лично мне это интересно прежде всего в качестве элемента более крупной фреймворка или либы для поэтапной обработки данных, но никак не в качестве замены баша.
0 mikhanoid21 апреля 2011 в 06:39#↵↑
Да Bash тут только при том, что с отладкой проблемы не такие уж и большие возникают.

А с синтаксисом… Ну, я ещё повторюсь: человек хочет сделать стандартную математическую абстракцию — композицию функций. Хочет выразить её через оператор, чтобы не писать f.compose(f1).compose(f2).compose(f3)… * использовать не разумно, потому что она часто встречается в коде. А |, известно из Bash, вполне себе уживается с редко используемым битовым or. Всё, imho, рационально.

Вы же, наверное, не критикуете библиотеки за то, что в них перегружают арифметику для работы с матрицами или длинными числами. Или когда + используется для конкатенации строк, или когда то же | используется для записи грамматических правил.
0 svetlov21 апреля 2011 в 06:53#↵↑
Пытаюсь вспомнить, в каком коде я видел f.compose(f1).compose(f2).compose(f3)… *
Нет, не вспоминается.
0 svetlov21 апреля 2011 в 06:58#↵↑
Зато что-то вроде
f.compose(
f1,
f2,
f3(arg)
)

писал не раз. Обратите внимание: композиция функций с использованием круглых скобок, таких привычных и родных.
0 mikhanoid21 апреля 2011 в 08:23#↵↑
Ай… Право же… Какой-то странный критерий оценки. Почему привычность должна быть приоритетнее удобства? Вероятно, нам с Вами друг друга просто не понять.
0 mikhanoid21 апреля 2011 в 08:24#↵↑
Нет. Ну в самом деле. А почему вы не настаиваете на том, чтобы вместо A * B + C писать: A.mul(B).add©? Привычнее же. Сплошные скобки… Прямо Lisp — классика.
0 svetlov21 апреля 2011 в 08:51#↵↑
Знаете, есть такая штука: принцип наименьшего удивления. Архитектурные решения, разработанные с использованием этого принципа, оказываются удобными. Так вот, использовать арифметические операторы для арифметических же действий — тоже привычно еще с детского садика.
0 mikhanoid21 апреля 2011 в 06:21#↵↑
Не чем 'непайпы', а как способ композиции функций. При чём тут перегрузка операторов — не очень понятно. Есть в математике такая стандартная операция — композиция. Философские причины того, почему в языке может быть перегружен оператор * для умножения матриц, а оператор | не может быть перегружен для композиции функций — лично для меня загадочны.
0 svetlov21 апреля 2011 в 06:50#↵↑
Перегружать — можно. Делайте на здоровье.

Используйте оператор | на полную катушку. Через год-два посчитайте, сколько раз за это время эта штука вам понадобилась. Перечитайте еще раз код, который эти пайпы использовал. И напишите success story, как все было хорошо и здорово, что вы уже не представляете себе жизни без чудо-механизма.
0 mikhanoid21 апреля 2011 в 08:20#↵↑
Не буду уже. Уже начал писать на Lua. А вы видели success story про умножение матриц при помощи *? Было бы интересно почитать, что там люди пишут.
0 svetlov21 апреля 2011 в 08:43#↵↑
Я читал много статей о numpy. Были среди них и success story.
0 Amper18 апреля 2011 в 03:19#
Это действительно гениально, причем и как идея, так и реализация! Я в восторге!
Обязательно начну использовать у себя.
+3 ingspree18 апреля 2011 в 12:25#↵↑
Не надо, пожалейте тех, кто будет работать с вами.
0 Amper18 апреля 2011 в 12:28#↵↑
Никто не будет, я буду использовать в СВОИХ скриптах, которыми пользуюсь только я. Конечно же нельзя использовать pipe в проектах, код которых будет использовать кто-то ещё.
НЛО прилетело и опубликовало эту надпись здесь
0 Suor18 апреля 2011 в 17:54#↵↑
Если нельзя использовать в таких проектах, то это как бы звоночек. Может лучше вообще не использовать?
0 Amper19 апреля 2011 в 02:04#↵↑
habrahabr.ru/blogs/python/117679/#comment_3834539
0 mas18 апреля 2011 в 04:47#
Главное — создать свой объект, т.к. в Питоне нельзя расширять предопределённые типы :(((. А трубы — это по практически то же, что и вызов методов:

[1,2,3,4] | where(lambda x: x<=2) | as_list

легко реализуется «питоническим» способом как:

KribleKrable([1,2,3,4]).where(lambda x: x<=2).as_list()
0 svetlov18 апреля 2011 в 05:10#↵↑
Есть неприятный нюанс. В каком namespace будет искать имена ваш KribleKrable?
Я имею в виду: как найдутся функции where и as_list из примера?
0 mas18 апреля 2011 в 05:19#↵↑
where и т.п. — методы объекта, возвращаемого функцией или конструктором KribleKrable. А сама KribleKrable ищется, очевидно, в том же пространстве имён, что и where из трубного примера.
0 svetlov18 апреля 2011 в 05:35#↵↑
«трубный» пример будет последовательно искать в локальном, глобальном и builtin пространствах имён.
Т.е. можно писать свои «трубы», оборачивая их декоратором @Pipe.
Наличие декоратора некрасиво, ну да ладно.

KribleKrable же должна явно содержать все доступные методы. Можно, конечно, выкрутиться.

1. Перегрузить __getattribute__ (или __getattr__ — не важно).
2. Хакнуть фрейм и вытащить f_globals/f_locals.
3. Эмулировать путь поиска имени.

Но это запутанная процедура, не делающая прочтение кода яснее — слишком логика отличается от привычной. Мне не нравится. Впрочем, «трубный» пример не нравится тоже.
+16 svetlov18 апреля 2011 в 05:05#
Сомнительный запашок у получающегося кода.

Перегрузка операций (любых) — не самый лучший способ построения каскадов генераторов.
Из-за этой перегрузки в записи возможны досадные ошибки.

Понятность снижается (а должна бы увеличиваться).
Оператор | может встречаться и в привычном контексте битовых операций.
Здесь же придется внимательно смотреть: это pipe или нет?
Если, скажем, numpy перегружает операторы для матриц — там ясна предметная область и не происходит
её перекрытия со стандартной семантикой. Если складываются два числа — они делают это по правилам элементарной арифметики. Две матрицы — тоже ничего нового.
В sqlalchemy для SQL запросов перегружаются все битовые операции.
При этом биты для чисел и запросы для SQL разведены по разным углам, очень редко пересекаясь в коде. По выражению практически всегда легко понять, где кто.
Здесь же | работает как битовый для чисел и pipe в стиле bash если самый правый операнд оказался типа Pipe.
Семантика разная, и две семантики легко могут пересекаться. Это неприятно.

Еще одно: эту штуку крайне легко сломать.
import pipe

class L(object):
def __init__(self, v):
self.v = v

def __or__(self, r):
return 'abra'

print L(range(5)) | pipe.as_list

Вроде бы класс L вполне невинен. Только, на беду, содержит оператор __or__, приоритет которого выше чем у
__ror__. Нехорошо…

Не все возможные занятные выкрутасы стоит использовать.

Сугубо личное мнение. Если кто не согласен — навязывать свое мнение не буду.
Раньше мне тоже нравились подобные полеты мысли: чем замудрённей — тем интересней.
Сейчас скорее признаю предлагаемый код unpythonic.
0 Amper18 апреля 2011 в 05:32#↵↑
Согласен с вашими доводами, конечно нужно знать, что делаешь и в серьезных проектах такое использовать нельзя.
Но это же красиво! Это «just for fan»! Почему бы и не поиспользовать это в своих скриптах? На мой взгляд, код многих мои скриптов с использованием pipe будет читаться и выглядеть гораздо проще и красивее, но это лишь мое мнение.
0 svetlov18 апреля 2011 в 05:43#↵↑
Если бы мы занимались увлекательным делом «напиши как можно хитрее» — тогда да, метод хорош.
Оно только выглядит проще — а понимается на самом деле сложнее чем запись «в лоб». Мы еще не переходили к обработке ошибок и чтению traceback — вот где поле непаханое.

И всё же повторюсь еще раз: предлагаемый подход ненадежен по построению.
Можно поиграть в занятную игру: придумывание кода, который валит библиотеку или заставляет ее работать «странно». Поверьте, этого кода много. У меня сразу нарисовалось несколько безобидных на первый взгляд вариантов. В примере я привел только самый короткий и очевидный.
+2 bormotov18 апреля 2011 в 08:37#↵↑
imho, дело не в написании хитрее. Люди ищут способы писать красивее.

Вот я уже не помню когда арфметическое или видел в живом коде. Как-то битовые операции остались в моём далеком прошлом :)
И перегрузку или тоже не припоминаю.

Хотя, всё что вы сказали — да, не добавляет радости к этой красоте.

С другой стороны, питон не призван быть супернадежным инструментом, многие вещи построены на доверии и предположении, что разработчик понимает, что он делает. А если есть сомнения — сомнений быть не должно. Команда внутри себя может дjговориться, например, что в рабочем кода нельзя использовать pipe, и делов-то.
+1 svetlov18 апреля 2011 в 08:41#↵↑
Множества, которые set/frozenset, тоже не используете?

> Команда внутри себя может дjговориться, например, что в рабочем кода нельзя использовать pipe, и делов-то.
Простите, потерял нить разговора. Вы предлагаете применять pipe исключительно в нерабочем коде?
+1 bormotov18 апреля 2011 в 08:51#↵↑
множества так сходу не примопню, нужно разработчиков спросить :)

эх, мне казалась мысль очень цельной.
Ок, коротко: pipe вообще не факт, что для использования в реальных проектах.
Это может быть просто как иллюстрация того, что может язык (и насколько просто он это может). Как исследование в каком направлении языку двигаться.
В конце концов — есть люди у которых ipython в качестве шела :)
0 VlK18 апреля 2011 в 15:23#↵↑
Кстати говоря, о множествах.

Вот если честь по чести, то эти самые множества используют тот же самый механизм переопределения __or__/__ror__; и ничего. Никто не кричит, что — О БОГИ! — программисты переопределили какую-то там побитовую операцию для каких-то там специальных типов.

Ну и что? В конце концов, реальный рабочий код пайп можно было бы разбавить нужными проверками и так далее.

Я все же утверждаю, что пайпы вполне работоспособны именно в качестве элемента какого-либо фреймворка, где можно твердо очертить область их применения.
0 svetlov18 апреля 2011 в 19:58#↵↑
Давайте поразмышляем, как сделать пайпы (с перегрузкой | и прочими плюшками) более безопасными в использовании.
+5 idle18 апреля 2011 в 07:14#↵↑
«just for fan»? Для вентилятора, пожалуй, в самый раз.
Рекомендую к просмотру и осмыслению — Ларри Гастингс: The Python That Wasn't.
0 anthonio18 апреля 2011 в 05:32#↵↑
Соглашусь с вами. Лишние выкрутасы. :)
0 mikhanoid18 апреля 2011 в 07:23#↵↑
Эмс… Не понятно, а в каком месте пайпы могут перемешаться с битовым or? Если утверждается, что пайпы можно только с пайпами объединять или с генераторами. То есть, пайп будет между пайпов, а битовый or будет внутри каких-нибудь скобочек внутри lambda или ещё где… В каком месте они смешаются?
+1 TheBits18 апреля 2011 в 07:40#↵↑
Может быть:
[1, 2, 3] | set([3, 4])
+2 svetlov18 апреля 2011 в 07:40#↵↑
Пайпы хотелось бы объединять только с пайпами или генераторами.
А на деле запрета нет, и глюкавый код написать вполне можно.
Более того, такую проверку (забудем про тормоза на время) не очень-то и вставишь.
Чтобы все работало, нужно «генератор» заменить на «итерируемый объект» — иначе пример со списком работать не будет.
А итерируемость — слишком широкое понятие. Строка, например, подходит.
Если вспомнить, что оператор | переопределен в том числе и для множеств — проблема перестает быть академической.
Чудить можно с размахом.
Самый простой пример (он ничего не ломает, но слегка обескураживает):
from pipe import as_list
a = {1, 2, 3}
b = {4, 5}
print a | b | as_list
0 YaakovTooth18 апреля 2011 в 08:35#↵↑
Только, на беду, содержит оператор __or__, приоритет которого выше чем у
__ror__. Нехорошо…
Опс. Нифига себе. Спасибо.
0 davinchi18 апреля 2011 в 17:48#↵↑
Кстати, вариант с KribleKrable этих недостатков лишён. А перегрузить класс и переопределить в нём часть функций можно всегда.
0 Suor18 апреля 2011 в 18:02#↵↑
Вариант с KribleKrable ещё не засоряет namespace. Но в нём значительно больше пунктуации, читабельность сомнительна.
0 davinchi18 апреля 2011 в 18:05#↵↑
И всё же, если я правильно помню, всевозможные ORM делают именно через классы, безо всяческих syntactic sugar.

Ну, а в варианте с | слишком много переносов строк.
0 ZZZ_Sochi18 апреля 2011 в 10:28#
Это всё, конечно, интересно и красиво, но я бы долго моргал глазами, если бы увидел это в чужом коде.
И я уже молчу про проблемы, описанные Андреем: к чёрту этот блек-джек!
Можно было бы подумать о такой организации настоящих пайпов модуля subprocess, но нужно хорошо подумать…
0 vkramskikh18 апреля 2011 в 12:15#
Заметной разницы нету, кроме обращения порядка действий. В идеале хотелось бы что-то вроде $ в haskell — порядок остается тем же, а скобки писать не надо
0 funca18 апреля 2011 в 12:35#
по-моему, аналогичный эффект можно получить с помощью композиции функций. т.е. «идеалистический» код может выглядеть следующим образом:
wtf = compose([where(lambda x: x % 3 == 1),
sum,
my_function])

result = wtf(x for x in range(100))

удобно если планируется реиспользовать функцию, хотя немного громоздко для однострочников. «библиотека», в первом приближении:
from functools import partial

compose2 = lambda f, g: lambda *args, **kws: g(f(*args, **kws))
compose = partial(reduce, compose2)
where = partial(partial, filter) # %) ?

+2 VlK18 апреля 2011 в 14:53#
Коллеги,

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

Комфортный синтаксис может быть необходимостью только в каком-то более широком контексте: фреймворке, бОльшей билиотеке, для каких-либо специальных задач.

Этот декоратор — proof of concept, не более того. Но красивый, тем и понравился :)
+3 ur00118 апреля 2011 в 15:23#
Хм…

Post.objects | where(user_id = 1) & where(is_published = True) | order('-time_published') | by_page(1, 10)

Забавно выходит :)
+2 VlK18 апреля 2011 в 15:32#↵↑
Вот именно как-то так я и вижу реальное применение подхода. Аккумулировать условия внутри пайпа, вычислять только по прямому требованию.

Только, в общем, джанговский ORM так и выглядит, только через точку; принципиальной разницы здесь нет.

Как насчет потока данных из сети? Скажем, такой синтаксис:

pipeline = socket | read_request | (callback & errback) | send_response
server.register(pipeline)
server.run(80)


здесь callback — сборка ответа на корректный запрос, errback — на некорректный; а оператор & — объединение корректного и некорректного обработчиков.
+1 ur00119 апреля 2011 в 15:14#↵↑
Ага :) А ещё:

image | scale(640, 960, crop = True) | rotate(PI/2) | mirrow(...) | invert()

На самом деле у подобного подхода есть любопытное преимущество: такие цепочки можно применять к любым объектам не изменяя их функциональности. Т.е. для image в этом примере не нужно добавлять методы к классу картинки, а scale, rotate, mirrow, invert могут быть универсальными для работы с разными типами.

И неудобство правда рядом:

image.scale(640, 960, crop = True).rotate(PI/2).mirrow(...).invert()

Так вполне может быть. Но вот залезать в глобальное пространство имён с функциями типа where, order, invert как-то некрасиво. Скорее, в реальности будет что-то типа:

from super.image.processor import i
image | i.scale(640, 960, crop = True) | i.rotate(PI/2) | i.mirrow(...) | i.invert()

А это уже не так элегантно.
+1 svetlov18 апреля 2011 в 19:59#↵↑
Поглядите на sqlalchemy. Там забавней — и строже одновременно.
0 ur00119 апреля 2011 в 15:24#↵↑
Честно говоря мне не очень нравится sqlalchemy. И Джанговский ORM меня не до конца устраивает. Я вот уже месяц собираюсь написать свою надстройку над Джанговским ORM :)
+1 LeNsTR18 апреля 2011 в 17:03#
Ваша статья натолкнула меня на некоторые мысли в контексте Ruby.

В нем проблемы с пайпами как таковой нет:

my_function(sum(filter(lambda x: x % 3 == 1, [x for x in range(100)])))

записывается как:

my_function ((1..100) . to_a . keep_if {|x| x % 3 == 1 } . reduce(:+))

Но с генераторами вида:

def fib
a, b = 0, 1
loop do
yield a
a, b = b, a + b
end
end

fib . take_while {|x| x < 10}

такое уже не проходит.

Приходится немножко извращаться:

def fib
a, b = 0, 1
res = []
loop do
return res unless yield a
res << a
a, b = b, a + b
end
end

fib {|x| x < 10} # => [0, 1, 1, 2, 3, 5, 8]

Неплохо, но хочется-то предыдущий вариант! :)

Конечно, можно использовать Fiber, дополнив его методом take_while:

class Fiber
def take_while
res = []
loop do
val = self.resume
return res unless yield val
res << val
end
end
end

def fib
Fiber.new do
a, b = 0, 1
loop do
Fiber.yield a
a, b = b, a + b
end
end
end

fib . take_while {|x| x < 10} # => [0, 1, 1, 2, 3, 5, 8]

Работает. Но что же это получается: каждую функцию, от которой требуется свойство бесконечного генератора, внутри оборачивать в Fiber? Noway! Я слишом ленив для такого.

И тут мой взор упал на декораторы питона: «Хорошая штука» — подумал я, сейчас возьму такую же в любимом руби и… внезапно в Ruby такого не оказалось.
«Вещь то полезная… надо реализовать!» — подумал небезызвестный Yehuda Katz и забацал поддержку декораторов для руби в 80 строчек кода.

Пишем свой декоратор:

class Generator < Decorator
def call(this, *args)
Fiber.new { loop { @method.bind(this).call(*args) { |x| Fiber.yield x } } }
end
end

и класс для бесконечного генератора чисел фибоначчи с «чистым» методом fib:

class FibGen
extend MethodDecorators

Generator()
def fib
a, b = 0, 1
loop do
yield a
a, b = b, a + b
end
end
end

FibGen.new.fib . take_while {|x| x < 10} # => [0, 1, 1, 2, 3, 5, 8]
FibGen.new.fib . take(7) . map {|x| x * 2} . reduce(:+) # => 40

Отлично! :)

Итого: добрая половина дня убита занятием вот этой замечательной фигней ^.^
+2 svetlov18 апреля 2011 в 21:58#
Вижу, разгорелся небольшой спор о том, что такое pythonic и что — нет.
Четкого определения нет и быть не может.
Мое чутье основывается на многолетнем чтении рабочей переписки разработчиков питона.
И на собственном опыте, конечно.
Иногда вроде бы красивая идея отвергается по результатам обсуждения.
Причины бывают разные.
Например, предлагаемый подход работает не в том духе, в котором сделано все остальное. Это может вводить пользователя в недоумение. В малых дозах — не страшно. В больших — становится натуральным ядом.
Случается и другое: работает в большинстве очевидных случаев, но в «темных углах» поведение непредсказуемо. Более того, правильное поведение неочевидно. Или мнения делятся «пополам-на-пополам».
Значит — решение плохое. Его можно применять в сторонних библиотеках — но в стандарт оно не войдет.
Бывает и третье. Все хорошо и понятно. Во мнениях сошлись. Но генерируемые ошибки (логичные и понятные) — неочевидны. Хороший спец понимает их с полуслова. «Простой программист» теряется в догадках. Это — тоже весомый минус. Предложение не будет принято.
Иногда ван Россум говорит: «Жопой чую, что-то здесь не так. Давайте отложим решение до лучших времен. И еще раз подумаем».

Это — строгие критерии отбора в core development team. Сторонние библиотеки не обязаны им следовать.

Более того. Уверен, что я перечислил далеко не все случаи — просто вспомнил о наиболее очевидных.

Что такое pythonic или unpythonic каждый решает сам для себя. И, тем не менее, я стараюсь следовать «чувству правильного», которое крайне неочевидно. Ориентир — тот дух, что пропитывает решения создателей языка.
Не одна моя поделка при внимательном рассмотрении оказалась — unpythonic. Красивая и лаконичная запись — и затем море проблем. Что-то улучшалось, гораздо большее — выбрасывалось. Жаль, но так лучше…
+1 idle19 апреля 2011 в 19:06#↵↑
Брутальный образ Гвидо вырисовывается — мол, жопой чую %)
Предлагаю первую букву BDFL развёртывать в brutal.
0 egorinsk18 апреля 2011 в 23:29#
Интересный подход. Но такие вещи все же надо делать на уровне языка, тогда это было бы вообще замечательно, а так это усложняет отладку кода и понимание кода всеми, кроме его автора. Переопределение операторов все же зло в плане читабельности кода, так как непонятно с чем ты имеешь дело, с переопределенным оператором или нативным.
0 eigrad18 апреля 2011 в 23:31#
В сочетании с ipython это просто шикарно для использования в качестве оболочки командной строки.
0 VlK 6 августа 2011 в 19:01#↵↑
Забрел тут в обсуждение такого рода пайпов пару месяцев случайно… А ведь действительно удобней получится. В живых интерпретаторах с CLI это действительно удобней и наглядней. Попробовать, что ли, написать что-нибудь..?

Обработку картинок?
0 loststylus18 апреля 2011 в 23:58#
Ох, если нужно писать понятно, то лучше уж писать «четверостишиями» действительно длинные связки, тогда названиями переменных можно одновременно и код документировать.

Code: Select all

class Pipe:

    
def __init__(self, function):
        
self.function = function

    
def __ror__(selfother):
        return 
self.function(other)

    
def __call__(self, *args, **kwargs):
        return 
Pipe(lambda xself.function(x, *args, **kwargs)) 
Image

dyvniy M
Topic author, Администратор
Администратор
Avatar
dyvniy M
Topic author, Администратор
Администратор
Age: 39
Reputation: 1
Loyalty: 1
Posts: 3472
Joined: Wed, 10 Oct 2012
With us: 9 years 3 months
Профессия: Программист
Location: Россия, Москва
ICQ Website Skype VK

#28by dyvniy » Fri, 3 Feb 2017, 12:30:16

ipython %quickref
http://vostryakov.ru/blog/16-otkryvayu-zanovo-ipython/
Spoiler
Открываю заново IPython - 18.03.2010

IPython - расширение стандартной интерактивной оболочки Питона. Легко ставить с помощью pip:

sudo pip install ipython
Джанго использует IPython, если выполнить: ./manage.py shell

Раньше я использовал в IPython историю введенных команд. Удобно можно выйти из оболочки, войти, а все введенные ранее команды сохранились в истории.

Но мимо меня прошла клевая функцональность IPython, как TAB completition. То есть набираете например import fun нажимаете TAB и видите варианты всех модулей начинающихся на fun. Тоже работает для классов, аттрибутов классов и модулей. В том числе и объявленных в интерактивной оболочке вами!

Основные фишки IPython
Дополнение: Спасибо всем за комментарии, добавили много интересного для меня! IPython много чего еще умеет, упомяну в кратце: помощь по объектам используя ? в конце названия объекта, например напишите float? и нажмите Enter. Много магических команд: %run, %edit, профилирование с помощью %prun и т.д. Полный список возможностей можно получить набрав %quickref

Комментарии: 5

keks.sw - 18.03.2010 IPython ради истории - это сильно :)
На сколько я понимаю, 2 самые частоиспользуемые фичи АйПайтона - комплишн и докстринги/сорцы по ?/??
Вообще он много чего умеет (%quickref), мне в свое время было ценен как замена шеллу (!command), транслятор шелл-комманд в питонячьи вызовы.
В последнее время все более популярен bpython - он умеет еще подсказывать и параметры к методам + показывает докстринги в процессе набора, но у него свои косяки.
Еще заслуживает внимания (и мне кажется самым перспективным) DreamPie. У него пока тоже хватает проблем (см. http://juick.com/kekssw/598027, например) и в макоси с ним не так уютно как под линуксом, зато он графический и лучше всего подходит на роль "шелла для написания программ"
Max - 18.03.2010 История и tab completition элементарно включаются в обычной питоновской консоли.
Плюс есть штуки типа bpython где это есть из коробки , плюс кучка других приятных фич типа подсветки и быстрого доступа к докстрингам. IPython это интересная штука, но использовать его для хранения истории это из пушки по воробьям. )
Roman Imankulov - 18.03.2010 Очень полезной для меня оказалась magic-функция %edit в IPython.

Задача выглядит так: необходимо посмотреть, как работает какая-то функция, или стандартный класс, или просто сделать выборку из списка моделей в Django. Причем нередко приходится делать несколько итераций (не тот параметр использовал, не тот метод вызвал и т.п.).

Подход "в лоб" заключается в том, чтобы аккуратно по порядку набрать все команды для проверки требуемой функциональности в консоли, и посмотреть на вывод. Если допущена ошибка в наборе команд, то набрать заново, либо воспользоваться историей, нажимая кнопочку "вверх", пока не надоест.

Более умный подход заключается в том, чтобы набрать последовательность команд в файле, а затем проделать последовательность действий "запустить в консоли - поправить - снова запустить" и т.п.

Команда edit позволяет сделать этот умный подход еще и удобным. Вот так я открываю временный файл для редактирования:

In [1]: edit /tmp/1.py


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

Вот тут, кстати, когда-то мной был описан еще один способ удобного использования IPython для быстрой отладки веб-сервисов.
Франковский Богдан - 22.03.2010 Под линукс есть даже более замечательная вещь - bpython.
RobertSit - 20.01.2017 The best fitness tip for building up your arms is to work opposite muscles in opposite sets of each other. The best example would be to work the triceps and then the biceps. Each has the opportunity to rest while the other is being worked. This minimizes your time and maximizes your workout.

https://www.acheterviagrafr24.com/
Image

dyvniy M
Topic author, Администратор
Администратор
Avatar
dyvniy M
Topic author, Администратор
Администратор
Age: 39
Reputation: 1
Loyalty: 1
Posts: 3472
Joined: Wed, 10 Oct 2012
With us: 9 years 3 months
Профессия: Программист
Location: Россия, Москва
ICQ Website Skype VK

#29by dyvniy » Fri, 28 Jul 2017, 01:46:31

for 2.7
ipython==5.4.1
Image

dyvniy M
Topic author, Администратор
Администратор
Avatar
dyvniy M
Topic author, Администратор
Администратор
Age: 39
Reputation: 1
Loyalty: 1
Posts: 3472
Joined: Wed, 10 Oct 2012
With us: 9 years 3 months
Профессия: Программист
Location: Россия, Москва
ICQ Website Skype VK

#30by dyvniy » Tue, 9 Jul 2019, 16:23:39

Написал утилиту для словарей Visual Studio,
дублирующие слова с маленькой буквы словами с большой.
Бесит, когда она не узнаёт слова в начале предложения.
Attachments
Dict.zip
(1.3 MiB) Downloaded 71 times
Image


Forum name: Python
Description: Программирование на супер модном мега крутом языке Питон.

Quick reply


Enter the code exactly as it appears. All letters are case insensitive.
Confirmation code
:) ;) :hihi: :P :hah: :haha: :angel: :( :st: :_( :cool: 8-| :beee: :ham: :rrr: :grr: :* :secret: :stupid: :music: View more smilies
   

Return to “Python”

Who is online (over the past 15 minutes)

Users browsing this forum: 2 guests