Раді Вас бачити! » Увійти » Створити новий профіль

python, cool & ugly

python, cool & ugly

Мої враження від питона:

cool?

>>> from functools import *
>>> plus2 = partial(lambda x,y: x+y, 2)
>>> plus2(10)
12

>>> reduce(lambda x, acc: x+acc, range(10), 1000)
1045

definitely.

>>> def f():
...    for x in range(10000000000): yield x
...
>>> [x*x for x in f() if x < 5]

^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
  File "<stdin>", line 2, in f
KeyboardInterrupt

not really. and no assignments in lambda??
   
Re: python, cool & ugly

а що ти хотів отримати?
 створив генератор з міліардом ітерацій і пробуєш пройти черех них, а воно триває довго.
   
Re: python, cool & ugly

а що ти хотів отримати?
 створив генератор з міліардом ітерацій і пробуєш пройти черех них, а воно триває довго.

Я думав, що yield видає елементи на вимогу. Як range в версії 3.

>>> for x in range(10000000000):
...   if (x > 3): break
...   else: print(x)
...
0
1
2
3
   
Re: python, cool & ugly

Це в python3?  В трійці я б очікував, що таке працює.
   
Re: python, cool & ugly

Це в python3?  В трійці я б очікував, що таке працює.

$ python -V
Python 3.4.5
   
Re: python, cool & ugly

range(10000000000) слишком большой список получается, в память не влазит. Лучше вот так делать -

def f(x):
   return range(x)
c = [x*x for x in f(5) if x < 5]
   
Re: python, cool & ugly

range(10000000000) слишком большой список получается, в память не влазит. Лучше вот так делать -

def f(x):
   return range(x)
c = [x*x for x in f(5) if x < 5]

range не створює жодного списку, лише ітератор, дивися мій пост вище, це працює без проблем:

>>> for x in range(10000000000):
...   if (x > 3): break
...   else: print(x)
   
Re: python, cool & ugly

range не створює жодного списку, лише ітератор, дивися мій пост вище, це працює без проблем:

>>> for x in range(10000000000):
...   if (x > 3): break
...   else: print(x)

 Согласен. Ну первый код у меня тоже работает. Просто брейкпоинта нету, поэтому итерация идет до 10000000000.
   
Re: python, cool & ugly

range is OK, yield isn't. Anyway, пішов спати. Happy hacking :)
   
Re: python, cool & ugly

Я думав, що yield видає елементи на вимогу. Як range в версії 3.

так і відбувається.
але далі
 [x*x for x in f() if x < 5]
ти хочеш згенерувати список і для втілення цього задуму викликаєш УСІ закладені в генератор ітерації почергово і якщо х менше 5 , то підносиш до квадрату і додаєш до новостворюваного списку.
   
Re: python, cool & ugly

import itertools

print([x*x for x in list(itertools.islice(range(10000000000),0,5,1))])

Бажаю удачі.


Останнє редагування: 16 листопада 2017 12:15:28 від Walter
   
Re: python, cool & ugly

import itertools

print([x*x for x in list(itertools.islice(range(10000000000),0,5,1))])

Бажаю удачі.

 Та же проблема с памятью.

 Я пробовал такое решение,

print(next(iter(())) if x >= 5 else x*x for x in range(10000000000))

но всё равно, память перегружается созданым списком.
   
Re: python, cool & ugly

Та же проблема с памятью.

 Я пробовал такое решение,

print(next(iter(())) if x >= 5 else x*x for x in range(10000000000))

но всё равно, память перегружается созданым списком.

у цьому варіанті

[x*x for x in list(itertools.islice(range(10000000000),0,5,1))]

немає проблеми з пам'яттю
т.я. оце

itertools.islice(range(10000000000),0,5,1))

вам уже легесенько зробить зріз з 5-ти елементів від нуля з кроком один з тих 10-ти мільярдів і не буде генерувати список з усіх елементів.
а потім загорне то в список
list(itertools.islice(range(10000000000),0,5,1))

а далі в квадрати зводити - то дрібниці

елемент списку в пітоні потребує приблизно n * <розмір вказівника> байтів
у вас 10 мільярдів елементів замовляється
10000000000 * 4 = 40000000000 байт - приблизно 39 мегабайт

якщо ви хочете знизити споживання пам'яті то слід дивитись на array, numpy.array
там можна виграти в 4-ри 8-м разів по пам'яті.

Ще раз бажаю удачі.

ЗІ.
І, я не пітонщик.
Пітон в мене то хоббі невеличке. :)
   
Re: python, cool & ugly

у цьому варіанті

[x*x for x in list(itertools.islice(range(10000000000),0,5,1))]
немає проблеми з пам'яттю
т.я. оце

itertools.islice(range(10000000000),0,5,1))

вам уже легесенько зробить зріз з 5-ти елементів від нуля з кроком один з тих 10-ти мільярдів і не буде генерувати список з усіх елементів.
а потім загорне то в список
list(itertools.islice(range(10000000000),0,5,1))

а далі в квадрати зводити - то дрібниці

елемент списку в пітоні потребує приблизно n * <розмір вказівника> байтів
у вас 10 мільярдів елементів замовляється
10000000000 * 4 = 40000000000 байт - приблизно 39 мегабайт

якщо ви хочете знизити споживання пам'яті то слід дивитись на array, numpy.array
там можна виграти в 4-ри 8-м разів по пам'яті.

Ще раз бажаю удачі.

ЗІ.
І, я не пітонщик.
Пітон в мене то хоббі невеличке. :)

 Вы правы, я случайно проверял с 2рым питоном. С 3им всё работает.
   
Re: python, cool & ugly

>>> def f():
...    for x in range(10000000000): yield x
...
>>> [x*x for x in f() if x < 5]
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
  File "<stdin>", line 2, in f
KeyboardInterrupt

До речі, наступне працює, значить проблема не з yield, a з list comprehension...

>>> for x in f():
...   if x > 5: break
...   else: print(x)

   
Re: python, cool & ugly

До речі, наступне працює, значить проблема не з yield, a з list comprehension...

>>> for x in f():
...   if x > 5: break
...   else: print(x)

що вам заважає зробити так:

def f():
   for x in range(10000000000):
      print("x=", x)
      yield x

[x*x for x in f() if x < 5]

і самому побачити, що відбувається?

саме так, проблема не в yield і не в if x < 5
проблема в тому, що витягується вся послідовність генератора
і лише потім буде зроблено зріз по if x < 5 перемножені значення і створений список

мабуть ви думаєте, чому list comprehension витягує всі значення з генератора f()?
ну він же не знає, що там буде зростаюча послідовність
та і не має цього знати
от йому і потрібні всі значення генератора і тільки потім він витягне ті значення, що відповідають умові if x < 5
а далі - все просто, тобто те що ви хочете з тим зрізом зробити

тобто пітон тут все робить вірно
не прискіпаєшся
:)


Останнє редагування: 16 листопада 2017 22:41:39 від Walter
   
Re: python, cool & ugly


мабуть ви думаєте, чому list comprehension витягує всі значення з генератора f()?
ну він же не знає, що там буде зростаюча послідовність
та і не має цього знати
от йому і потрібні всі значення генератора і тільки потім він витягне ті значення, що відповідають умові if x < 5
а далі - все просто, тобто те що ви хочете з тим зрізом зробити

:)

Точно! Я був неправий. В хаскелі це теж не працює:

[x | x <- [1..], x < 5]

Вольтер,  :-B
   
Re: python, cool & ugly

Але, якщо ви дійсно (як програміст) знаєте послідовність яку формує генератор, і знаєте, що вона зростаюча, то тоді ще варіант:

>>> import itertools
>>> [i*i for i in itertools.takewhile(lambda x: x<5, range(10000000000))]
[0, 1, 4, 9, 16]

це практично те, що ви хотіли мабуть.
працює швидко, при заданій умові в лямбді звісно. :)
   
Re: python, cool & ugly

насколько все же некомфортно для глаз выглядит код на пайтоне....  фигурные скобки в других языка мне всегда нравились больше
   
Re: python, cool & ugly

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

Для будь якої людини, не комфортним буде все, що вона мало або зовсім не розуміє.
Це стосується всього, як мов програмування так і людських мов спілкування, або будь чого іншого.

Рішення тут два. Або вивчити і зрозуміти і побачити ту красу яку інші не бачать, або просто забити і не перейматись.
Саме рішення залежить від того, хто його приймає і від його сталення до світу, що його оточує.

Те ж саме на Java 8 у функціональному стилі:

    public static void main(String[] args) {
       List<Long> longs = LongStream.range(1, 10000000000L).filter(i -> i < 5).mapToObj(i -> (i * i)).collect(Collectors.toList());
       System.out.println(longs);
    }

трошки задовго, але виконується.

А це те ж саме, тільки з фігурними дужками, як ви любите:

    public static void main(String[] args) {
        List<Long> longList = new ArrayList<>();
        for (long i = 1; i < 10000000000L; i++) {
            if (i < 5) {
                longList.add(i * i);
            }
        }
        System.out.println(longList);
    }

Що скажете?
Комфортніше аніж:

[i*i for i in itertools.takewhile(lambda x: x<5, range(10000000000))]

Особисто для мене немає поганих і некомфортних мов і речей.
Всьому своє місце.
І будь яка сутність має право на існування.

Стосовно мов програмування - то просто інструменти.
І їх нема поганих або хороших.
Кожен інструмент створювався зі своєю метою.

Ви ж, наприклад, не будете на роботу їздити, скажімо, на вантажівці, вірно?
Ви виберете легковик.
І це буде вірно.
І цеглу мабуть не додумаєтесь возити легковим авто, вірно?
Але легкове авто не гірше і не ліпше вантажівки.
І вантажівка не ліпше і не гірше.
Вони просто різні і всьому своє призначення.

Так і Python і Java обоє класні і обоє мають свою нішу.


Останнє редагування: 17 листопада 2017 11:40:31 від Walter
   
Re: python, cool & ugly

Що скажете?
Комфортніше аніж:

[i*i for i in itertools.takewhile(lambda x: x<5, range(10000000000))]

Це комфортніше в хаскел:

[i*i | i <- takeWhile (<5) [1..]]
   

Цю тему переглядають:

0 Користувачів і 1 гість
 
Повна версія