Найти - Пользователи
Полная версия: Прошу совета в части освовения
Начало » Python для новичков » Прошу совета в части освовения
1
Sabach
Доброго дня всем!
Ранее уже обращался за помощью. Помогли добрыми советами. За что огромное спасибо.
Python изучаю самостоятельно для возможной смены специальности по итогам успешной сдачи финального задания. Пока в самом начале пути. Курс, который прохожу, дан в сжатом виде, без особых пояснений и примеров. Поэтому без живого общения сложно выходит. Да, я могу найти ответы на промежуточные задания, но тогда теряется сам смысл моего обучения. Т.к. цель именно научиться, понять и смочь, а не для галочки.
Дана задача: По данному натуральному n ≤ 9 выведите лесенку из n ступенек, i-я ступенька состоит из чисел от 1 до i без пробелов.
Ответ подсмотрел:
 n=int(input("Введите целое число до 9 включительно: "))
for i in range(n):
    for i in range(1,i+2):
        print(i, end=' ')
    print()
Результат:
 Введите целое число до 9 включительно: 3
1 
1 2 
1 2 3
Вроде логика понятна, но остались вопросы.
В данном коде, как я понял:
1. Задаем размер диапазона (например: 3)
2. Для каждого значения из заданного диапазона создаем еще один, который начинается с “1” и прибавляем 2 к порядковому номеру значения. Т.е. 1 значится на нулевом месте, получаем 2; 2 значится не первом месте получаем 3.
Не понятно:
1. Почему
1 - здесь просто 1?. Если задали i+2, то должна быть и двойка
1 2
1 2 3 - Почему закончилось на 3? Тройка стоит на 2-ом месте +2, должно добавиться 4. Но опять же, мы задали диапазон из 3 значений.
Возможно коряво написал и вопросы кажутся глупыми, но из-за отсутствия понимания я не могу (вернее, не хочу) продвигаться дальше…
Может есть где простые задачки с описанием решения, решая которые можно понять что-почем?
За свои сорок лет бОльшим дураком не выглядел, но обратиться больше не к кому…
py.user.next
Sabach
Курс, который прохожу, дан в сжатом виде, без особых пояснений и примеров. Поэтому без живого общения сложно выходит.
Дело не в живом общении. Ты неправильно составил себе программу обучения и из-за этого неправильно себе подбираешь курсы. Ты знаешь, что бывают курсы, составленные людьми, ничего не смыслящими в преподавании? Оттуда ты и получаешь вот это “найдите то, найдите это, а это вам домашнее задание”. Они не способны научить чему-то, даже если умеют это сами.
И в итоге ты их недоработки добираешь на форумах.

  
>>> def f():
...     n = int(input("Введите число от 1 до 9 включительно: "))
...     for i in range(n):
...         for j in range(i + 1):
...             print(j + 1, end='')
...         print()
... 
>>> f()
Введите число от 1 до 9 включительно: 9
1
12
123
1234
12345
123456
1234567
12345678
123456789
>>>

Sabach
Возможно коряво написал и вопросы кажутся глупыми, но из-за отсутствия понимания я не могу (вернее, не хочу) продвигаться дальше
В прошлом топе я тебе говорил, что сливание всего воедино в программировании не приветствуется. Только если ты для машины код делаешь и оптимизируешь его по максимуму, там можно слить всё воедино автоматически, так как человек это читать не будет потом никогда.
В данном примере, который ты подсмотрел, опять всё слито воедино и оно как-то работает, но как, понять очень сложно. Вот будь уверен, что в случае возникновения логической ошибки в этом коде даже автор этого кода её не заметит и этот код будет выдавать неправильный вывод в каком-нибудь из случаев.

И я написал пример, где всё разделено. Читай его и понимай, и обращай внимание на мелочи и на то, что там введена переменная j, которая не даёт мозгам запутываться и тормозиться с вопросом “а вон там переменная i и вон там переменная i, а что в этой переменной на каждом шаге?”.

Sabach
За свои сорок лет бОльшим дураком не выглядел, но обратиться больше не к кому
Тебе нужно разработать программу обучения для себя. Потом под эту программу подобрать методики обучения себя. А потом уже искать ресурсы для удовлетворения этим методикам - курсы, книги, видео, коды, преподаватели, дидактические материалы. Бери по максимуму. Добудь курс вуза, который учит по данной специальности. Вузы, как правило, подотчётны министерству образования, поэтому свои курсы они не лепят на коленке, а выстраивают в соответствии с требованиями закона.
В то же время в Интернете могут существовать школы, которые набирают кого угодно в качестве преподавателей, которые разрабатывают какие угодно курсы и которые не отвечают за результат обучения ни перед кем.
Sabach
Спасибо за рекомендации…
Скачал 2 тома Лутца. Может путем наименьшего сопротивления мозги встанут на место..
Введение многообещающе (на то оно и введение)
AD0DE412
py.user.next
Бери по максимуму
+
Sabach
Всем доброго дня!
Задание: Напишите программу (файл arithmetic.py), которая предлагала бы пользователю решить пример 4 * 100 - 54. Потом выводила бы на экран правильный ответ и ответ пользователя. Подумайте, нужно ли здесь преобразовывать строку в число.
Мой вариант:
 a=4*100-54
print ("Решите задачу:\n 4*100-54=?")
while True:
    try:
        b=float(input ("Введите Ваш ответ:\n"))
        if a==b:
            print("Поздравляю! Ответ правильный.")
        else:
            print ("К сожалению, Вы ошиблись.\nПравильный ответ:",a)
    except(ValueError):
        print("Введите числовое значение!")
    else:
       break
Среди ответов других пользователей понравился своей компактностью такой:
 print('Ex:1. Solve the equation 4*100-54', end='\n\n') 
user_answer = int(input("input your answer here: "))
right_answer =  4 * 100 - 54
if user_answer == right_answer:
	print ("Your answer: {0}. Computer calculate: {1}".format(user_answer, right_answer))
else:
	print("Your answer is wrong")
Вопрос, по большей части к py.user.next: насколько мой алгоритм близок к рекомендованной ранее модульности и что не так?
py.user.next
Sabach
Вопрос, по большей части к py.user.next: насколько мой алгоритм близок к рекомендованной ранее модульности и что не так?
Надо вычисление формулы перенести ближе к циклу.

Алгоритм для решения задачи:
1. Вывести на экран информацию о программе.
2. Инициализировать переменные.
2.1. Вычислить результат выражения 4 * 100 - 54.
2.2. Сохранить результат вычисления выражения в переменной.
3. Принять ввод от пользователя.
3.1. Принять ввод в виде строки от пользователя.
3.2. Преобразовать ввод от пользователя из строки в число.
4. Сравнить числовой результат выражения с числовым пользовательским вводом.
5. Вывести результат сравнения на экран.

Sabach
Среди ответов других пользователей понравился своей компактностью такой
Он не столько компактный, сколько правильный по последовательности шагов. Где-то шаги склеены в один, но на начальных этапах их надо разделять, потому что в голове ты всегда раздельно думаешь, а склеивание шагов появляется только в коде и оно не всегда является правильным действием.

Но, хоть код у него и выглядит красиво, но он всё равно далеко не идеальный. Эта красота обманчива.

Вот он сделал так
  
user_answer = int(input("input your answer here: "))
А где гарантия, что ему введут число, а не буквы или точки? Он слил воедино раздельные вещи и потерял из-за этого возможность вставить проверку введённой строки, которая должна находиться между int( и input(. Он сам себя лишил этой возможности, добавив в код красоты.

Другое дело, если бы он записал вот так
  
user_answer = input("input your answer here: ")
user_answer_number = int(user_answer)
Вроде бы тоже можно буквы или точки ввести и всё упадёт (программа выдаст отказ = программа откажет).
Но тут можно вставить проверку между input и int.

Мы видим место, где нужна проверка, и мы просто добавляем эту проверку
  
user_answer = input("input your answer here: ")
if not user_answer.isdigit():
    print("Error: not a number")
    sys.exit(1)
user_answer_number = int(user_answer)
То есть две строки, которые были до внесённого изменения в код, остались на своих местах и остались неизменными. Но при этом проверка появилась и не допустит теперь неправильного ввода от пользователя.

Код надо писать так, чтобы в него изменения возможно было только добавлять. То есть если код написан так, что для его изменений необходимо его переделывать, то это некачественно оформленный код. Если переделываешь код, то вот тот код, который ты переделываешь, а не просто добавляешь к нему, написан некачественно. Он может правильно работать, он может быть красивейшим, но в деле он оказывается затратным при дальнейшей работе с ним.


Если же твой код анализировать, то у тебя в оператор try … except … else занесено всё, что не относится к этому оператору try … except … else .
В try у тебя должна происходит только проверка ввода, проверка его на ошибку, а у тебя в try занесено и сравнение, и вывод результата на экран, которые никакого отношения к этому try не имеют. Это нарушение модульности, нужно вынести сравнение и вывод результата за пределы try … except … else , чтобы внутри остался только ввод строки и преобразование её в число. А вообще там должно остаться только преобразование в число, потому что try только к этому относится. Но так как ты слил шаги ввода строки и преобразования строки в число воедино, то чтобы в try оставить только преобразование строки в число, тебе придётся код переделывать, ты не можешь к этому коду просто добавить что-то и получить нужный результат.

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

Твой код после моих исправлений
  
>>> def f():
...     print('Решите задачу:\n4 * 100 - 54 = ?')
...     a = 4 * 100 - 54
...     b = None
...     while True:
...         s = input('Введите Ваш ответ:\n')
...         try:
...             b = float(s)
...             break
...         except ValueError:
...             print('Введите числовое значение!')
...     if a == b:
...         print('Поздравляю! Ответ правильный.')
...     else:
...         print('К сожалению, Вы ошиблись.')
...         print('Правильный ответ:', a)
... 
>>> f()
Решите задачу:
4 * 100 - 54 = ?
Введите Ваш ответ:
abc
Введите числовое значение!
Введите Ваш ответ:
def
Введите числовое значение!
Введите Ваш ответ:
12
К сожалению, Вы ошиблись.
Правильный ответ: 346
>>> 
>>> 
>>> f()
Решите задачу:
4 * 100 - 54 = ?
Введите Ваш ответ:
346
Поздравляю! Ответ правильный.
>>>
Sabach
Спасибо за советы!
у тебя в try занесено и сравнение, и вывод результата на экран, которые никакого отношения к этому try не имеют. Это нарушение модульности
Согласен. Навертел, будь здоров. Впервые пробовал исключения.
Так ещё и try есть не во всех языках программирования. И в питоне тоже try работает медленнее, чем if, поэтому его избегают довольно часто
Насколько скорость обработки try критична? Мне показался этот вариант обработки более универсальным. Да и везде пишут (про забор, на котором много чего написано, я помню) отработку исключений связкой try…except.
Про строковые методы (isalnum, isalpha, isdecimal, isdigit, isidentifier, isnumeric) ранее не слышал. Если б не пример выше, даже б не знал.
py.user.next
Sabach
Насколько скорость обработки try критична?
Ну, вот на примере деления двух чисел с проверкой деления на ноль можно увидеть, как растёт стек из-за оператора try. Ему нужно больше запоминать в стеке.
  
>>> def f1():
...     a, b = 1, 0
...     c = None
...     try:
...         c = a / b
...     except ZeroDivisionError:
...         print('error')
...     print(c)
... 
>>> def f2():
...     a, b = 1, 0
...     c = None
...     if b != 0:
...         c = a / b
...     else:
...         print ('error')
...     print(c)
... 
>>> import dis
>>> 
>>> dis.dis(f1)
  2           0 LOAD_CONST               4 ((1, 0))
              2 UNPACK_SEQUENCE          2
              4 STORE_FAST               0 (a)
              6 STORE_FAST               1 (b)
  3           8 LOAD_CONST               0 (None)
             10 STORE_FAST               2 (c)
  4          12 SETUP_EXCEPT            12 (to 26)
  5          14 LOAD_FAST                0 (a)
             16 LOAD_FAST                1 (b)
             18 BINARY_TRUE_DIVIDE
             20 STORE_FAST               2 (c)
             22 POP_BLOCK
             24 JUMP_FORWARD            28 (to 54)
  6     >>   26 DUP_TOP
             28 LOAD_GLOBAL              0 (ZeroDivisionError)
             30 COMPARE_OP              10 (exception match)
             32 POP_JUMP_IF_FALSE       52
             34 POP_TOP
             36 POP_TOP
             38 POP_TOP
  7          40 LOAD_GLOBAL              1 (print)
             42 LOAD_CONST               3 ('error')
             44 CALL_FUNCTION            1
             46 POP_TOP
             48 POP_EXCEPT
             50 JUMP_FORWARD             2 (to 54)
        >>   52 END_FINALLY
  8     >>   54 LOAD_GLOBAL              1 (print)
             56 LOAD_FAST                2 (c)
             58 CALL_FUNCTION            1
             60 POP_TOP
             62 LOAD_CONST               0 (None)
             64 RETURN_VALUE
>>> 
>>> dis.dis(f2)
  2           0 LOAD_CONST               4 ((1, 0))
              2 UNPACK_SEQUENCE          2
              4 STORE_FAST               0 (a)
              6 STORE_FAST               1 (b)
  3           8 LOAD_CONST               0 (None)
             10 STORE_FAST               2 (c)
  4          12 LOAD_FAST                1 (b)
             14 LOAD_CONST               2 (0)
             16 COMPARE_OP               3 (!=)
             18 POP_JUMP_IF_FALSE       30
  5          20 LOAD_FAST                0 (a)
             22 LOAD_FAST                1 (b)
             24 BINARY_TRUE_DIVIDE
             26 STORE_FAST               2 (c)
             28 JUMP_FORWARD             8 (to 38)
  7     >>   30 LOAD_GLOBAL              0 (print)
             32 LOAD_CONST               3 ('error')
             34 CALL_FUNCTION            1
             36 POP_TOP
  8     >>   38 LOAD_GLOBAL              0 (print)
             40 LOAD_FAST                2 (c)
             42 CALL_FUNCTION            1
             44 POP_TOP
             46 LOAD_CONST               0 (None)
             48 RETURN_VALUE
>>> 
>>> print(dis.code_info(f1))
Name:              f1
Filename:          <stdin>
Argument count:    0
Kw-only arguments: 0
Number of locals:  3
Stack size:        11
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
   0: None
   1: 1
   2: 0
   3: 'error'
   4: (1, 0)
Names:
   0: ZeroDivisionError
   1: print
Variable names:
   0: a
   1: b
   2: c
>>> 
>>> print(dis.code_info(f2))
Name:              f2
Filename:          <stdin>
Argument count:    0
Kw-only arguments: 0
Number of locals:  3
Stack size:        2
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
   0: None
   1: 1
   2: 0
   3: 'error'
   4: (1, 0)
Names:
   0: print
Variable names:
   0: a
   1: b
   2: c
>>>
Следовательно, при тысячах выполнений одной и той же функции try каждый раз больше работает с памятью, чем такой же if. А работа с памятью занимает как минимум время.

А вообще в плане программирования, если ты через обычный if не можешь ничего проверить и тебе нужно для этого использовать какой-нибудь синтаксический сахар обязательно вроде try, потому что ты не можешь классическим if'ом пользоваться, то очень скоро ты попадёшь на язык, где будет всё только классическое и ты там два байта связать не сможешь.
Ну, это как примерно в школе ученик со сломавшимся калькулятором вдруг резко теряет возможность решать задачи на производные и интегралы, потому что без калькулятора-то он таблицу умножения не знает. Потом он сколько угодно может рассказывать, как он умеет решать производные, только вот никто не будет ему подсказывать, как 7 на 8 умножить. Ему поставят два в документ, которую он потом не сможет исправить, а задачу он тоже не решит. В итоге из-за какой-то глупости он всё потеряет. А надо было учить таблицу умножения, потом учить производные и интегралы, а потом, уже после школы, где-нибудь на работе он может для скорости использовать калькулятор. И то, если у калькулятора вдруг сядет батарейка или он в воду упадёт (или на него вода прольётся, наоборот), то это никак не должно вырубить ему работу, он легко должен перейти на собственные мозги со встроенным калькулятором.
Вот так же и if'ы - это классика и это должен знать каждый. А если ты не можешь if делать, значит ты его не знаешь и тебе его надо изучать. Если у тебя проблемы с if'ом (ты его можешь делать, но он делается тяжело), значит ты его не знаешь и тебе его надо изучать. Он должен легко делаться. И вот тогда ты сможешь выбирать: я могу легко сделать if здесь, а могу легко сделать try здесь. И там ты уже задаёшь вопрос “а чем это будет в плане будущей поддержки кода и будущей эволюции кода? а не придётся ли этот try потом переделывать в if? не станет ли он в новых условиях непригоден к использованию?”. Вот исходя из этого ты и будешь выбирать их, а не исходя из того, что “это вот удобно мне сделать, а это вот я не знаю достаточно и путаюсь”.

Sabach
Про строковые методы (isalnum, isalpha, isdecimal, isdigit, isidentifier, isnumeric) ранее не слышал.
Вообще ввод проверяется регулярными выражениями. Это модуль re.

Пример
  
>>> import re
>>> 
>>> while True:
...     s = input('Введите число:\n')
...     if re.search(r'^(0|[1-9]\d*)$', s) is None:
...         print('Это не число "{}"'.format(s))
...         continue
...     n = int(s)
...     print('Число {}'.format(n))
... 
Введите число:
abc
Это не число "abc"
Введите число:
1a
Это не число "1a"
Введите число:
000
Это не число "000"
Введите число:
00
Это не число "00"
Введите число:
123
Число 123
Введите число:
0
Число 0
Введите число:
00
Это не число "00"
Введите число:
00 1
Это не число "00 1"
Введите число:
001
Это не число "001"
Введите число:
01
Это не число "01"
Введите число:
111
Число 111
Введите число:
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
EOFError
>>>
Обрати внимание на числа вида 0 и не числа вида 000. Также он не пропустит числа со знаком “+” или со знаком “-”, потому что мы так хотим. Мы можем точно задать, что будет числом, а что не будет числом. Вот это и есть программирование - когда ты делаешь то, что тебе надо, а не то, что там само получается и ты должен под это подстраиваться.
Например в функции int() или float() ты никак не можешь запретить приём чисел со знаком или в виде чисел с нулями в начале. И так ты становишься обязан считать числом то, что они тебе скажут считать числом.
То есть ты не должен писать программы, которые тебя куда-то ведут. Ты должен писать программы, которые ты ведёшь туда, куда надо тебе.
Тогда у тебя программы будут получаться. Будет тяжело, когда программа не захочет идти туда, куда ты её направляешь, а захочет идти в свою сторону какую-то, но в этом и заключается мастерство. Ты наберёшь опыт - и программы начнут получаться.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB