Перейти к содержимому

Ans python что это

  • автор:

Python: Прошу объяснить, почему не меняется значение переменной

Добрый день. Прохожу сейчас на edx.org курс по Питону. Попалась задача. Я ее решил, но во время решение возник вопрос, который не могу понять. Интересует выражение “ans = (high+low)/2” и его позиционирование в коде.

inpt='' low = 0 high = 100 # "Позиция 1" - программа постоянно спрашивает "Is your secret number 50?" # ans = (high+low)/2 print 'Please think of a number between 0 and 100!' while inpt != 'c': # "Позиция 2" - все работает норм ans = (high+low)/2 print 'Is your secret number ' + str(ans) +'?' inpt = raw_input("Enter 'h' to indicate the guess is too high. Enter 'l' to indicate the guess is too low. Enter 'c' to indicate I guessed correctly.") if inpt == 'h': high = ans elif inpt == 'l': low = ans elif inpt == 'c': inpt == 'c' else: print 'Sorry, I did not understand your input.' if inpt == 'c': print 'Game over. Your secret number was: ' + str(ans) 

Суть вопроса: Я не понимаю, в чем разница между размещением “ans = (high+low)/2” в позиции 1 и 2. Почему в “Позиции 1” пересчет ans не происходит, а в “Позиции 2” происходит? Как я себе понимаю, не должно быть разницы между позицией 1 и 2, так как после ввода ‘h’ или ‘l’ меняются переменные high и low и соответственно уже новый\пересчитанный ans должен использоваться в следующей итерации. Но почему то, если ans = (high+low)/2 запихнуть в 1ую позицию, то он упорно запоминает 100+0/2 и не хочет воспринимать измененные после первой итерации low и high. Спасибо.

Именованные аргументы — Python: Функции

В Python у функций могут быть еще и именованные аргументы — keyword arguments.

Например, мы вызываем следующую функцию:

def bar(length, char1, char2): return (char1 + char2) * length + char1 print(bar(5, '-', '*')) # => -*-*-*-*-*- 

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

Именованные аргументы

Чтобы передать именованные аргументы в функцию, нужно указать их имена, которые были заданы при объявлении функции:

def bar(length, char1, char2): return (char1 + char2) * length + char1 print(bar(length=3, char1='-', char2='*')) # => -*-*-*- print(bar(char1='-', char2='*', length=3)) # => -*-*-*- print(bar(char2='*', length=3, char1='-')) # => -*-*-*- 

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

Значения аргументов по умолчанию

Предположим, что char1 и char2 чаще получают одни и те же значения. В такой ситуации удобно указать значения по умолчанию:

def bar(length, char1='-', char2='*'): return (char1 + char2) * length + char1 print(bar(5)) # => -*-*-*-*-*- print(bar(3, '.')) # => .*.*.*. print(bar(2, ':', '|')) # => :|:|: 

Теперь предположим, что нас устраивает значение по умолчанию для char1 , но мы хотим задать свое значение для char2 . Это можно сделать с помощью именованных аргументов:

print(bar(4, char2='#')) # => -#-#-#-#- print(bar(char2='$', length=3)) # => -$-$-$- 

Здесь имеет значение порядок групп аргументов — позиционные значения должны быть указаны до именованных. Иначе мы получим ошибку:

print(bar(char2='%', 2)) # => SyntaxError: positional argument follows keyword argument 

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

bar(char2='!') # TypeError: bar() missing 1 required positional argument: 'length' 

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

def f(*args, x=None, y=None): print('args =', args, ', x =', x, ', y =', y) f(*(1, 2), x='a', *[3, 4], y='b', *(5, 6)) # => args = (1, 2, 3, 4, 5, 6), x = a, y = b 

В данном примере переменная args содержит все позиционные аргументы, которые были переданы функции. А переменные x и y содержат значения аргументов, которые были переданы по именам.

Случаи применения именованных аргументов

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

make('circle', 300, 150, 10, None, 2.5, False) 
make( shape='circle', x=300, y=150, radius=10, line_pattern=None, line_width=2.5, fill=False ) 

Такой код читать проще.

У вышеупомянутого правила есть пара исключений:

  • Если по названию функции можно сразу понять, что она выполняет и какие параметры принимает, то имена аргументам не задаются. Например, можно понять, что скрывается за значениями в вызове point3d(10, 50, 21) или rgb(0, 255, 0)
  • Не нужно указывать имена аргументам, которые объявлены через * . У этого нет смысла и возможности
def sum(*args):  sum(x1=1, x2=2) # TypeError: sum() got an unexpected keyword argument 'x1' 

В таких функциях имя args недоступно извне, ведь это не один аргумент, а получатель произвольного их количества.

Выводы

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Понимание работы логических операций and, or и not

Важно! Операторы and и or закорачивают вычисление своих операндов (т.е. используют замыкания): правый операнд вычисляется лишь в том случае, если его значение необходимо для получения истинного значения в операциях and или or . Другими словами, замыкания в логических операциях используются для запуска второй части или последующих частей логического выражения только в том случае, если это актуально!

  • or — оценивает второй аргумент, только если первый равен False . Если какой либо операнд в цепочке or является истиной, немедленно возвращается результат — первое истинное значение.
  • and — оценивает второй аргумент, только если первый равен True . Если в цепочке and все операнды являются истиной, результатом будет последнее значение. А если какой-либо из операндов является False , результатом будет первое ложное значение.
  • not имеет более низкий приоритет, чем операторы сравнения, так not a == b интерпретируется как not (a == b) , а выражение a == not b вовсе является синтаксической ошибкой. Единственный логический оператор с одним аргументом. Он принимает один аргумент x и возвращает противоположный результат: False для истинного значения и True для ложного значения.

Операторы and и or не приводят свои результаты принудительно к значениям True или False , а возвращают один из своих операндов. Такой подход позволяет использовать эти операторы в более общих, а не только булевых операциях. Если другие операторы, прежде чем выполнить операцию, вычисляют все свои операнды, то в случае операторов and и or с их семантикой закорачивания необходимость вычисления правого операнда определяется результатом вычисления левого.

Из булевых операторов, not имеет самый высокий приоритет, а or самый низкий, так что A and not B or C эквивалентно (A and (not B)) or C . Как всегда, скобки могут быть использованы для выражения желаемого приоритета в операциях.

Логические операции, упорядоченные по приоритету выполнения:

  1. not x — если x ложно, то возвращается True , иначе False .
  2. x and y — если x ложно, то возвращается x , иначе у .
  3. x or y — если x ложно, то возвращается у , иначе x

Объяснение работы замыкания c оператором and :

a = 'a' b = 'b' c = 'c' >>> a and b # 'b' >>> '' and b # '' >>> a and b and c # 'c' 

Пояснения к примеру выше с оператором and :

  1. Оператор and вычисляет значения в булевом контексте слева направо. Значения 0 , » , [] , () , <> и None являются ложью, все остальное является истиной. Если у and оба операнда являются истиной, результатом будет последнее значение.
  2. Если какой-либо из операндов является ложью, результатом будет первое такое значение. В данном случает это » — пустая строка, первое значение которое является ложью.
  3. Все значения являются истиной, так что в результате мы получаем последнее c .

Объяснение работы замыкания c оператором or :

a = 'a' b = 'b' >>> a or b # 'a' >>> '' or b # 'b' >>> '' or [] or <> # <> >>> def func(): . return 1 >>> a or func() # 'a' 

Пояснения к примеру выше с оператором or :

  1. Оператор or вычисляет значения в булевом контексте слева направо. Если операнд является истиной, or немедленно возвращает результат. В данном случае a , первое истинное значение.
  2. or вычисляет выражение » , которое является ложью, затем b, которое является истиной, и возвращает его значение.
  3. Если все значения являются ложью, or возвращает последнее.
  4. Обратите внимание, что or вычисляет операнды до тех пор, пока не найдет истинное значение, остальное игнорируется. Это имеет значение, когда вычисление операнда дает сторонние эффекты. В данном случае функция func() не вызывается, так как для получения результата выражения с оператором or достаточно того, что первый операнд a является истиной.

Другие примеры с and и or :

>>> a = 'one' >>> b = 'two' >>> 1 and a or b # 'one' >>> 0 and a or b # 'two' >>> a = '' >>> b = 'two' # 'a' - пустая строка, которую Python считает ложью, # следовательно 1 and '' дает '', а '' or 'two' дает 'two'. >>> 1 and a or b # 'two' 

Практическое использование замыканий and и or в кодовой базе.

Внимание! Замыкания в операциях and и or можно использовать с пользой в вычислениях для экономии ресурсов, сокращения времени выполнения и т.д., только будьте осторожны! Необходимо четко понимать как работают замыкания в операторах and и or .

  • Экономия ресурсов и времени выполнения при помощи and ;
  • Проверка предварительных условий перед выражением;
  • Определение значения по умолчанию при помощи or ;
  • Пример использования замыканий в функциях all() и any() .

Экономия ресурсов и времени выполнения при помощи and .

Рассмотрим реальный пример из модуля base64 стандартной библиотеки Python, который использует замыкание в оператора if . Исследуем функцию b64decode , которая берет строку (или объект, подобный байтам) и декодирует ее:

# взято из Lib/base64.py def b64decode(s, altchars=None, validate=False): """Decode the Base64 encoded bytes-like object or ASCII string s. [docstring cut for brevity] """ s = _bytes_from_decode_data(s) if altchars is not None: altchars = _bytes_from_decode_data(altchars) assert len(altchars) == 2, repr(altchars) s = s.translate(bytes.maketrans(altchars, b'+/')) # использование замыкания с оператором `and` if validate and not re.fullmatch(b'[A-Za-z0-9+/]*=', s): raise binascii.Error('Non-base64 digit found') return binascii.a2b_base64(s) 

Смотрим на оператор if , который помечен комментарием. В условии сначала проверяется аргумент validate , а только потом результат работы функции re.fullmatch() . Аргумент validate сообщает функции, хочет ли пользователь вообще проверять строку, которую нужно декодировать. Обратите внимание, что если validate=False то сопоставление регулярного выражения не запускается (срабатывает замыкание). Если порядок операндов поменять, то результат остался такой же, но было бы потрачено гораздо больше времени.

Проверка предварительных условий перед выражением.

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

Допустим есть последовательность и нужно взять элемент по индексу, но последовательность может оказаться пустой или ее длина может быть меньше индекса. Например:

>>> lst = [0, 1, 2] >>> lst[3] # Traceback (most recent call last): # File "", line 1, in # IndexError: list index out of range 

Используем проверку предварительных условий:

>>> lst = [0, 1, 2] >>> if lst and len(lst) >=3: . lst[3] 

Здесь, в условии сначала проверяется что список НЕ пустой и только после этого вычисляется длинна этого списка. Если список пустой, то его длина проверяться не будет и условие if завершиться.

Еще один пример из модуля enum :

# взято из Lib/enum.py def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1): """ Convenience method to create a new Enum class. """ # [сокращено для краткости] # special processing needed for names? if isinstance(names, str): names = names.replace(',', ' ').split() # смотрим на следующие условие if isinstance(names, (tuple, list)) and names and isinstance(names[0], str): original_names, names = names, [] last_values = [] # [сокращено для краткости] 

Более длинный оператор if содержит три выражения, разделенных операторами and , и первые два выражения нужны для того, чтобы убедиться, можно ли безопасно выполнить последнее.

  • isinstance(names, (tuple, list)) — проверяет, является ли names кортежем или списком. Если не является то условие завершается.
  • далее names проверяется пусто оно или нет. Если элементов нет то условие завершается.
  • если names не пустой, то можно безопасно выполнить последнюю проверку, связанную с индексацией names[0] , а именно isinstance(names[0], str) .

Определение значения по умолчанию при помощи or .

Замыкание с помощью логического оператора or может использоваться для присвоения переменным значений по умолчанию. Вот пример:

# test.py greet = input("Ваше имя >> ") or "незнакомец" print(f"Привет, greet>!") # $python3 -i test.py # Ваше имя >> # Привет, незнакомец! 

Если запустить этот пример и ничего не вводя нажать Enter, то получим вывод «Привет, незнакомец!». Что тут происходит? Если ничего не вводить и нажать Enter, то функция input() вернет пустую строку » , что является False . Следовательно, оператор or видит ложное значение слева и должен оценить правый операнд. Для определения окончательное значение выражения or оценивает правый операнд и если он True , то возвращает его значение.

Еще пример присвоения значение по умолчанию (используя or ) для изменяемого аргумента из стандартной библиотеки Python.

# взято из Lib/cgitb.py class Hook: """A hook to replace sys.excepthook that shows tracebacks in HTML.""" def __init__(self, display=1, logdir=None, context=5, file=None, format="html"): self.display = display # send tracebacks to browser if true self.logdir = logdir # log tracebacks to files if not None self.context = context # number of source code lines per frame self.file = file or sys.stdout # self.format = format 

Этот код взят из модуля cgitb и определяет sys.stdout как значение по умолчанию для переменной self.file . Определение функции __init__ имеет file=None в качестве ключевого аргумента, так почему бы просто не написать file=sys.stdout ?

Проблема в том, что sys.stdout может быть изменяемым объектом, поэтому использование file=sys.stdout в качестве ключевого аргумента со значением по умолчанию не будет работать так, как ожидается. Это легче продемонстрировать со списком в качестве аргумента по умолчанию, хотя принцип тот же:

>>> def addend(val, l=[]): . l.append(val) . print(l) >>> addend(3, [1, 2]) # [1, 2, 3] >>> addend(5) # [5] >>> addend(5) # [5, 5] >>> addend(5) # [5, 5, 5] 

Обратите внимание на три последовательных вызова addend(5) . Ожидается, что вызов addend(5) со значением по умолчанию l=[] будет вести себя одинаково, но т.к. список является изменяемым объектом, то вызовы добавляют значения val к значению по умолчанию [] , при этом список растет! Дополнительно смотрите материал «Список Python как аргумент по умолчанию».

Пример использования замыканий or и and в функциях all() и any() .

Если в выражении генератора использовать оператор моржа := , и принимать во внимание тот факт, что функции all() и any() также используют замыкания, то можно использовать следующую конструкцию для извлечения первого истинного элемента.

any(predicate(witness := item) for item in items) 

Другими словами, если какой-либо элемент item удовлетворяет условию в функции predicate() , то переменная witness сохранит его значение!

Например, если последовательность содержит много целых чисел, как выяснить, есть ли там какие-либо нечетные числа, и как вывести первое из них?

items = [14, 16, 18, 20, 35, 41, 100] any_found = False for item in items: any_found = item % 2 if any_found: print(f"Найдено нечетное число item>.") break 

Теперь все это сравним со следующим кодом:

>>> items = [14, 16, 18, 20, 35, 41, 100] >>> is_odd = lambda x: x % 2 >>> if any(is_odd(witness := item) for item in items): . print(f"Найдено нечетное число witness>.") # Найдено нечетное число 35. 

Функции и их аргументы

Python 3 логотип

В этой статье я планирую рассказать о функциях, именных и анонимных, инструкциях def, return и lambda, обязательных и необязательных аргументах функции, функциях с произвольным числом аргументов.

Именные функции, инструкция def

Функция в python — объект, принимающий аргументы и возвращающий значение. Обычно функция определяется с помощью инструкции def.

Определим простейшую функцию:

Инструкция return говорит, что нужно вернуть значение. В нашем случае функция возвращает сумму x и y.

Теперь мы ее можем вызвать:

 
  Функция может и не заканчиваться инструкцией return, при этом функция вернет значение None:

Функция может принимать произвольное количество аргументов или не принимать их вовсе. Также распространены функции с произвольным числом аргументов, функции с позиционными и именованными аргументами, обязательными и необязательными.

Функция также может принимать переменное количество позиционных аргументов, тогда перед именем ставится *:

    Как видно из примера, args - это кортеж из всех переданных аргументов функции, и с переменной можно работать также, как и с кортежем.

Функция может принимать и произвольное число именованных аргументов, тогда перед именем ставится **:

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

Анонимные функции, инструкция lambda

Анонимные функции могут содержать лишь одно выражение, но и выполняются они быстрее. Анонимные функции создаются с помощью инструкции lambda. Кроме этого, их не обязательно присваивать переменной, как делали мы инструкцией def func():

 

Для вставки кода на Python в комментарий заключайте его в теги

  • Модуль csv - чтение и запись CSV файлов
  • Создаём сайт на Django, используя хорошие практики. Часть 1: создаём проект
  • Онлайн-обучение Python: сравнение популярных программ
  • Книги о Python
  • GUI (графический интерфейс пользователя)
  • Курсы Python
  • Модули
  • Новости мира Python
  • NumPy
  • Обработка данных
  • Основы программирования
  • Примеры программ
  • Типы данных в Python
  • Видео
  • Python для Web
  • Работа для Python-программистов
  • Сделай свой вклад в развитие сайта!
  • Самоучитель Python
  • Карта сайта
  • Отзывы на книги по Python
  • Реклама на сайте

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *