• B правой части каждого сообщения есть стрелки и . Не стесняйтесь оценивать ответы. Чтобы автору вопроса закрыть свой тикет, надо выбрать лучший ответ. Просто нажмите значок в правой части сообщения.

  • Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

Проверка на ввод числа Python

id2746

Green Team
12.11.2016
435
644
BIT
19
Функция проверки на ввод пользователем числа.
При вводе числа все ОК, оно возвращается.
При вводе НЕ числа, происходит перезапуск функции до тех пор пока не будет введено число, но в итоге возвращается None.
Объясните пожалуйста что не так. Заранее спасибо.
Python:
def digit_check():
    try:
        lenght = int(input('Enter the number:\n'))
        return lenght
    except ValueError:
        print('Please, enter the number\n')
        digit_check()

a = digit_check()
print(a)

Скрин работы прилагаю:
2021-06-23_10-13-28.png
 
Решение
Тем не менее кто сможет, объясните почему не работал мой вариант, который я расписал пошагово.
TL/DR: Ты получаешь 'return None' потому, что твоя функция ничего не возвращает после первого вызова (если при первом запросе указан не int), а return от вложенных функций у тебя никак не обрабатывается.

Как вариант, можно сделать так (добавлен return в except):
Python:
def digit_check():
    try:
        lenght = int(input('Enter the number:\n'))
        return lenght
    except ValueError:
        print('Please, enter the number\n')
        return digit_check()

a = digit_check()
print(a)

1624444062773.png

explorer

Platinum
05.08.2018
1 080
2 474
BIT
0
НЕ нужно функцию вызывать внутри функции принт, вот и весь расклад.
Это неверно:

Python:
a = digit_check()
print(a)

А это правильно:

Python:
digit_check()

ЛЮБАЯ функция возвращает результат. А если явно не указано что возвращать, то возвращается None.
 

larchik

Администратор
07.06.2019
400
477
BIT
410
Python:
def digit_check():
    try:
        lenght = int(input('Enter the number:\n'))
        print(f'Your enter: ' + str(lenght))
    except ValueError:
        print('Please, enter the number\n')
        digit_check()

digit_check()
 

larchik

Администратор
07.06.2019
400
477
BIT
410
ЛЮБАЯ функция возвращает результат. А если явно не указано что возвращать, то возвращается None.
Правильно ли я понимаю, что в коде @id2746 происходит следующее:
если вводим текст, а не число, то выполняется except, затем рекурсивно выполняется функция digit_check(), и когда эта функция наконец получает число, то она возвращает его в себя же уровнем выше. Поэтому не выполняется последняя инструкция print(a).
А далее я не понимаю, почему функция digit_check() возвращает None (то есть выполнился try?), ведь она так и не получила на вход число, должен снова выполниться except.
У меня хоть и получился рабочий код, но чисто интуитивно, без понимания процесса внутри.

UPD:
я бы эту функцию выполнил без try/except, а поместил код в цикл вроде такого:
Python:
key = True
while key:
    lenght = input('Enter the number:\n')
    if lenght.isdigit():
        key = False
    else:
        print('error')
print(lenght)

Мне кажется, так более человекопонятно

UPD2:
Сорри, сразу по ссылке не перешел, там частично содержится ответ на мой вопрос.
Ну в общем допер, почему так происходит) Спасибо
 
Последнее редактирование:

id2746

Green Team
12.11.2016
435
644
BIT
19
НЕ нужно функцию вызывать внутри функции принт, вот и весь расклад.
Это неверно:

Python:
a = digit_check()
print(a)

А это правильно:

Python:
digit_check()

ЛЮБАЯ функция возвращает результат. А если явно не указано что возвращать, то возвращается None.
По поводу первого, того что не правильно, это же вынесено за функцию. Сделано для проверки того что возвращается.

Правильно ли я понимаю, что в коде @id2746 происходит следующее:
если вводим текст, а не число, то выполняется except, затем рекурсивно выполняется функция digit_check(), и когда эта функция наконец получает число, то она возвращает его в себя же уровнем выше. Поэтому не выполняется последняя инструкция print(a).
А далее я не понимаю, почему функция digit_check() возвращает None (то есть выполнился try?), ведь она так и не получила на вход число, должен снова выполниться except.
У меня хоть и получился рабочий код, но чисто интуитивно, без понимания процесса внутри.

UPD:
я бы эту функцию выполнил без try/except, а поместил код в цикл вроде такого:
Python:
key = True
while key:
    lenght = input('Enter the number:\n')
    if lenght.isdigit():
        key = False
    else:
        print('error')
print(lenght)

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


По моей логике, если человек вводит цифру, то все ОК и функция возвращает число. Если введено не число, то выдается предупреждение об ошибке (+ отрабатывается exception) и снова вызывается функция.
Это работает, но мне не понятно, почему когда наконец выполняется мое условие (вводится число) функция его не возвращает, ведь все идет пошагово...

Проблему то я решил, благодаря @Pernat1y, но без понимания как оно работает, по сравнению с моим кодом:
Python:
def digit_check():
    while True:
        try:
            lenght = int(input('Enter the number:\n'))
            return lenght
        except ValueError:
            print('Please, enter the number\n')
            continue

UPD:
Новое решение понял, цикл while будет выполняться бесконечно до тех пор, пока не будет получен правильный ввод (ввод числа), и функция прекратит выполнение по return.

Тем не менее кто сможет, объясните почему не работал мой вариант, который я расписал пошагово.
 
Последнее редактирование:

Pernat1y

Well-known member
05.04.2018
1 443
135
BIT
0
Тем не менее кто сможет, объясните почему не работал мой вариант, который я расписал пошагово.
TL/DR: Ты получаешь 'return None' потому, что твоя функция ничего не возвращает после первого вызова (если при первом запросе указан не int), а return от вложенных функций у тебя никак не обрабатывается.

Как вариант, можно сделать так (добавлен return в except):
Python:
def digit_check():
    try:
        lenght = int(input('Enter the number:\n'))
        return lenght
    except ValueError:
        print('Please, enter the number\n')
        return digit_check()

a = digit_check()
print(a)

1624444062773.png
 
Решение

explorer

Platinum
05.08.2018
1 080
2 474
BIT
0
UPD:
я бы эту функцию выполнил без try/except, а поместил код в цикл вроде такого:
Python:
key = True
while key:
lenght = input('Enter the number:\n')
if lenght.isdigit():
key = False
else:
print('error')
print(lenght)
Мне кажется, так более человекопонятно
Этот код тоже некорректный:

1. ТС-у нужна функция
2. Если пункт 1 не учитывать, то правильный код будет выглядеть так:

Python:
while True:
    lenght = input('Enter the number:\n')
    if lenght.isdigit():
        print(lenght)
        break
    else:
        print('error')

Почему так? Потому что внутри цикла есть условные операторы. Соответственно, при выполнении условия и будет напечатан тот или иной результат. Для прерывания цикла есть break. Код стал чуть короче, и нет никакого выноса за пределы цикла.

А ошибка ТС состоит в следующем:
При срабатывании эксцепшена функция не возвратила результат. Но по-умолчанию в таком случае, ЛЮБАЯ функция обязательно возвратит None, то есть "ничего". И это "ничего" при использовании принт выводится на печать, всё просто.
 

larchik

Администратор
07.06.2019
400
477
BIT
410
Это работает, но мне не понятно, почему когда наконец выполняется мое условие (вводится число) функция его не возвращает, ведь все идет пошагово...
Дружище, как я понимаю, все кроется в рекурсии.
Твоя функция рекурсивная. Она выполняется один раз на каждом шаге так:
1. ты ввел неверное значение, то есть return функции не выполнился, но сама функция уже выполнилась, то есть далее ->
2. выполнился except
3. в except снова выполняется твоя функция
4. теперь ты ввел верное значение
5. значит твоя функция выполнила try и вернула в return значение из lenght
6. рекурсия пошла в обратном порядке, мы выходим из функции вверх
7. так как функция в верхней иерархии уже была выполнена на шаге 1 и 2 (когда мы шли вниз по иерархии), то она больше не выполняется
8. а значит больше не выполняет и return
9. рекурсия завершается, и функция должна что-то вернуть, даже если небыло return. В таком случае в python функция неявно возвращает None

Коллеги поправят, если я ошибся.
 

larchik

Администратор
07.06.2019
400
477
BIT
410
1. ТС-у нужна функция
ну так этот код поместить в функцию и все, я думал это очевидно. Или в чем некорректность?
я принял участие в этом топике не потому, что понимаю, а как раз наоборот )) самому интересно докопаться до сути
 
Последнее редактирование:

explorer

Platinum
05.08.2018
1 080
2 474
BIT
0
ну так этот код поместить в функцию и все, я думал это очевидно. Или в чем некорректность?
я принял участие в этом топике не потому, что понимаю, а как раз наоборот )) самому интересно докопаться до сути

Некорректность в том, что имя lenght не определено (используйте IDE чтобы увидеть это предупреждение). Любая переменная должна быть определена ДО её использования. В таком случае корректный код может быть таким:

Python:
key = True
lenght = ''
while key:
    lenght = input('Enter the number:\n')
    if lenght.isdigit():
        key = False
    else:
        print('error')
print(lenght)

Здесь lenght является пустым значением, но это значение записывается в память и создаёт там объект. Внутри цикла этот объект перезаписывается, и получает новое значение. Но любой код должен хорошо читаться, и лишние строки всегда лучше оптимизировать, поэтому в итоге код и превратился в тот что я выше уже написал:

Python:
while True:
    lenght = input('Enter the number:\n')
    if lenght.isdigit():
        print(lenght)
        break
    else:
        print('error')

В этом варианте объект создаётся уже прямо непосредственно в цикле, то есть нет лишней операции перезаписи объекта. А значит выполнится он быстрее. Надеюсь теперь понятно. А вообще цикл while не советую нигде использовать - он очень медленный по сравнению с тем же for например.
 

larchik

Администратор
07.06.2019
400
477
BIT
410
Любая переменная должна быть определена ДО её использования.
но как я понял, в этом и фишка python, что переменная может быть определена на месте.
цикл while не советую нигде использовать - он очень медленный по сравнению с тем же for
я не знаю, как использовать цикл for в python таким же образом, как, например, в java. В python мне известен только вариант for i in последовательность
как в данном случае использовать for? (я имею ввиду случай ТСа)
используйте IDE чтобы увидеть это предупреждение
да, ты прав, лень было грузить ide, у меня слишком дохлый ноут)

Если не доставит тебе неудобств, то лучше обращайся ко мне на "ты". Если затруднительно, то ок, будем на "вы" )

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

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

explorer

Platinum
05.08.2018
1 080
2 474
BIT
0
Вот предупреждение с твоего кода:

663.png


Любая переменная является ссылкой на объект в памяти. Питон это объектно-ориентированный язык, он работает с объектами. Сборщик мусора удаляет значение, на которое ссылается переменная. Объекты удаляются только когда на них больше нет ссылок. Поэтому перезаписываются значения, а сама ссылка на объект остаётся.

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

9820.png



Python:
from itertools import cycle

lenght = ['']
for i in cycle(range(len(lenght))):
    x = input('Enter the number:\n')
    lenght.append(x)
    if lenght[-1].isdigit():
        print('Number:', lenght[-1])
        break
    else:
        print("Not a number:", lenght[-1])
 

Art Pro

New member
04.01.2023
1
0
BIT
0
Ещё можно вот так:

Python:
def get_number():
    while True:
        x = input('Enter the number:\n')
        if x.isdigit():
            return int(x)
        else:
            print("Not a number:", x)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!