Основы функций в Python

PythonBeginner
Практиковаться сейчас

Введение

В этом практическом занятии вы научитесь определять и использовать функции на Python. Мы начнем с простых примеров и постепенно будем увеличивать сложность.

Давайте начнем!

Достижения

  • Функции на Python

Определить функцию на Python

Для определения функции на Python вам нужно использовать ключевое слово def, за которым следует имя функции и круглые скобки, которые могут содержать аргументы. Тело функции отступлено и следует за символом :.

Откройте новый интерпретатор Python.

python3

Вот пример простой функции, которая принимает один аргумент x и возвращает квадрат x:

def square(x):
  return x ** 2

В этом примере функция square принимает один аргумент x и возвращает квадрат x. Значение возвращается вызывающей стороне с помощью инструкции return.

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

result = square(5)  ## result is 25
print(result)

Если функция не имеет инструкции return, по умолчанию она вернет None. Например:

def square(x):
  print(x ** 2)

result = square(5)  ## result is None
print(result)

Вы должны знать разницу между инструкциями return и print. Инструкция print используется для вывода значения на экран, а инструкция return используется для возврата значения из функции.

Также можно использовать инструкцию return для завершения выполнения функции заранее. Например:

def find_first_positive(numbers):
  for number in numbers:
    if number > 0:
      return number
  return None

result = find_first_positive([-1, -2, 3, -4, 5])  ## result is 3
print(result)

В этом примере функция find_first_positive возвращает первое положительное число в списке numbers, или None, если не найдено положительных чисел. Инструкция return завершает выполнение функции сразу, как только найдено положительное число.

Аргументы функции

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

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

def rectangle_area(length, width=1):
  return length * width

print(rectangle_area(5))  ## Output: 5
print(rectangle_area(5, 2))  ## Output: 10

В этом примере аргумент width имеет значение по умолчанию 1. Если функция вызывается с только одним аргументом, то для width используется значение по умолчанию 1.

Попробуйте сами: определите функцию под названием power, которая принимает два аргумента: основание x и показатель степени n. Сделайте аргумент показателя степени необязательным, с значением по умолчанию 2. Затем вызовите функцию с разными значениями для основания и показателя степени.

def power(x, n=2):
  return x ** n

print(power(2))  ## Output: 4
print(power(2, 3))  ## Output: 8

Подсказка типа аргумента

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

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

Например, рассмотрите следующую функцию, которая принимает два аргумента, целое число и строку, и возвращает их конкатенацию:

def concatenate(a: int, b: str) -> str:
    return str(a) + b

print(concatenate(1, "world")) ## "1world"

В этом примере подсказки типов int и str указывают, что первый аргумент a должен быть целым числом, а второй аргумент b должен быть строкой.

Подсказки типов также можно использовать с классами и их экземплярами, например:

class MyClass:
    pass

def my_function(a: MyClass) -> None:
    pass

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

Также в Python есть модуль под названием typing, который содержит полезные типы, такие как List, Tuple, Dict, Set и т.д., которые можно использовать для указания подсказок о типах элементов в коллекции.

from typing import List, Tuple
def my_function(a: List[int], b: Tuple[str, int]) -> None:
    pass

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

Документационная строка (docstring)

Документационная строка (docstring) — это строковый литерал, который встречается в качестве первой инструкции в определении модуля, функции, класса или метода. Такая docstring становится специальным атрибутом __doc__ этого объекта.

Docstring используются для документирования кода и записываются в простом тексте. Они заключаются в тройные кавычки """ и обычно размещаются в начале определения функции.

def my_function():
    """This is a docstring."""
    pass

Docstring обычно содержат краткое описание функции, ее аргументов и возвращаемого значения. Они также могут содержать более длинное описание поведения функции.

def my_function(a: int, b: int) -> int:
    """Return the sum of a and b.

    Args:
        a (int): The first number.
        b (int): The second number.

    Returns:
        int: The sum of a and b.
    """
    return a + b

Возвращение нескольких значений

В Python функция может возвращать несколько значений с использованием кортежа. Вот пример функции, которая вычисляет минимальное и максимальное значения списка:

def min_max(numbers):
  return min(numbers), max(numbers)

nums = [1, 2, 3, 4, 5]
min_val, max_val = min_max(nums)
print("Minimum value:", min_val)  ## Output: "Minimum value: 1"
print("Maximum value:", max_val)  ## Output: "Maximum value: 5"

В этом примере функция min_max возвращает кортеж, содержащий минимальное и максимальное значения списка numbers. Кортеж распаковывается в переменные min_val и max_val при вызове функции.

Вот еще один пример возврата нескольких значений из функции:

def get_student_info(name):
  if name == "John":
    return "John", "Doe", "Computer Science"
  elif name == "Jane":
    return "Jane", "Smith", "Physics"
  else:
    return "Unknown", "Unknown", "Unknown"

first_name, last_name, major = get_student_info("John")
print("First name:", first_name)  ## Output: "First name: John"
print("Last name:", last_name)  ## Output: "Last name: Doe"
print("Major:", major)  ## Output: "Major: Computer Science"

first_name, last_name, major = get_student_info("Jane")
print("First name:", first_name)  ## Output: "First name: Jane"
print("Last name:", last_name)  ## Output: "Last name: Smith"
print("Major:", major)  ## Output: "Major: Physics"

first_name, last_name, major = get_student_info("Bob")
print("First name:", first_name)  ## Output: "First name: Unknown"
print("Last name:", last_name)  ## Output: "Last name: Unknown"
print("Major:", major)  ## Output: "Major: Unknown"

В этом примере функция get_student_info принимает имя студента и возвращает кортеж, содержащий имя, фамилию и специальность студента. Кортеж распаковывается в отдельные переменные при вызове функции.

Если имя студента не распознается, функция возвращает кортеж со значениями "Unknown".

Ключевые аргументы

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

Вот пример функции, которая принимает два аргумента: имя и сообщение:

def greet(name, message):
  print("Hello, " + name + "! " + message)

greet(message="How are you?", name="John")  ## Output: "Hello, John! How are you?"

В этом примере функция greet вызывается с аргументами "John" и "How are you?", но аргументы задаются в другом порядке, чем они определены в функции. Используя ключевые аргументы, вы можете задавать аргументы в любом порядке и сделать код более читаемым.

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

def greet(name, message):
  print("Hello, " + name + "! " + message)

greet("John", message="How are you?")  ## Output: "Hello, John! How are you?"

В этом примере аргумент name задается как позиционный аргумент, а аргумент message задается как ключевой аргумент.

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

def create_user(name, age=18, gender="unknown"):
  print("Creating user:", name, age, gender)

create_user("John")  ## Output: "Creating user: John 18 unknown"
create_user("Jane", gender="female")  ## Output: "Creating user: Jane 18 female"
create_user("Bob", 25, "male")  ## Output: "Creating user: Bob 25 male"

В этом примере функция create_user принимает три аргумента: name, age и gender. Аргументы age и gender имеют значения по умолчанию, поэтому они являются необязательными. Используя ключевые аргументы, вы можете указать только те аргументы, которые хотите передать, и для остальных будут использоваться значения по умолчанию.

Args и Kwargs

В Python можно использовать синтаксис *args и **kwargs, чтобы определить функцию, которая может принимать переменное количество аргументов.

Синтаксис *args используется для передачи переменного количества неименованных аргументов в функцию. Например:

def print_numbers(*args):
  for arg in args:
    print(arg)

print_numbers(1, 2, 3, 4, 5)  ## Output: 1, 2, 3, 4, 5
print_numbers(10, 20, 30)  ## Output: 10, 20, 30

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

Синтаксис **kwargs используется для передачи переменного количества именованных аргументов в функцию. Например:

def print_keywords(**kwargs):
  for key, value in kwargs.items():
    print(key, ":", value)

print_keywords(name="John", age=30, city="New York")
## Output:
## name : John
## age : 30
## city : New York

print_keywords(country="USA", population=327000000)
## Output:
## country : USA
## population : 327000000

В этом примере функция print_keywords принимает переменное количество именованных аргументов и выводит их в консоль. Синтаксис **kwargs используется для определения функции, и аргументы передаются в функцию в виде словаря.

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

def print_info(title, *args, **kwargs):
  print(title)
  for arg in args:
    print(arg)
  for key, value in kwargs.items():
    print(key, ":", value)

print_info("Person", "John", "Jane", "Bob", age=30, city="New York")
## Output:
## Person
## John
## Jane
## Bob
## age : 30
## city : New York

В этом примере функция print_info принимает фиксированный аргумент title, за которым следуют переменное количество неименованных аргументов (*args) и переменное количество именованных аргументов (**kwargs). Аргументы передаются в функцию в том порядке, в котором они определены: сначала title, затем *args, и наконец **kwargs.

Синтаксис *args и **kwargs может быть полезен, когда вы хотите определить гибкую функцию, которая может принимать переменное количество аргументов. Они также могут сделать код более читаемым, позволяя избежать использования жестко закодированных имен аргументов в определении функции.

Вот пример функции, которая использует *args и **kwargs для создания словаря аргументов:

def create_dict(**kwargs):
  return kwargs

my_dict = create_dict(name="John", age=30, city="New York")
print(my_dict)  ## Output: {'name': 'John', 'age': 30, 'city': 'New York'}

my_dict = create_dict(a=1, b=2, c=3)
print(my_dict)  ## Output: {'a': 1, 'b': 2, 'c': 3}

В этом примере функция create_dict принимает переменное количество именованных аргументов и возвращает их в виде словаря. Синтаксис **kwargs используется для определения функции, и аргументы передаются в функцию в виде словаря.

Вы также можете использовать оператор * для "распаковки" списка или кортежа в отдельные аргументы при вызове функции. Например:

def print_numbers(*args):
  for arg in args:
    print(arg)

numbers = [1, 2, 3, 4, 5]
print_numbers(*numbers)  ## Output: 1, 2, 3, 4, 5

tuple_of_numbers = (10, 20, 30)
print_numbers(*tuple_of_numbers)  ## Output: 10, 20, 30

В этом примере оператор * используется для распаковки списка numbers и кортежа tuple_of_numbers в отдельные аргументы при вызове функции print_numbers.

Вы также можете использовать оператор ** для "распаковки" словаря в именованные аргументы при вызове функции. Например:

def print_keywords(**kwargs):
  for key, value in kwargs.items():
    print(key, ":", value)

my_dict = {'name': 'John', 'age': 30, 'city': 'New York'}
print_keywords(**my_dict)
## Output:
## name : John
## age : 30
## city : New York

another_dict = {'country': 'USA', 'population': 327000000}
print_keywords(**another_dict)
## Output:
## country : USA
## population : 327000000

В этом примере оператор ** используется для распаковки словарей my_dict и another_dict в именованные аргументы при вызове функции print_keywords.

Lambda-функции

В Python можно использовать "lambda-функции" для создания анонимных функций. Lambda-функции - это небольшие функции, которые не имеют имени и обычно определяются и вызываются в одну строку кода.

Вот пример lambda-функции, которая принимает два аргумента и возвращает их сумму:

sum = lambda x, y: x + y

result = sum(1, 2)  ## result is 3

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

Можно ли использовать обычную функцию вместо lambda-функции для определения той же функции?

def sum(x, y):
  return x + y

result = sum(1, 2)  ## result is 3

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

Вот пример использования lambda-функции в качестве аргумента для функции sorted:

words = ["apple", "banana", "cherry", "date"]
sorted_words = sorted(words, key=lambda x: len(x))
print(sorted_words)  ## Output: ['apple', 'date', 'banana', 'cherry']

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

Вот пример определения lambda-функции inline:

result = (lambda x: x ** 2)(5)  ## result is 25

В этом примере lambda-функция принимает один аргумент x и возвращает квадрат x. Lambda-функция определяется и вызывается в одну строку кода, и result назначается переменной result.

Lambda-функции часто используются в Python для коротких, простых функций, которые не нуждаются в повторном использовании в других частях кода. Это удобный способ определить небольшие функции "на лету", не нужно определять отдельную функцию с использованием ключевого слова def.

Локальная и глобальная область видимости

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

Вот пример глобальной переменной:

message = "Hello, world!"

def greet():
  print(message)

greet()  ## Output: "Hello, world!"

В этом примере переменная message определена вне функции greet, поэтому это глобальная переменная. Функция greet может получить доступ и распечатать переменную message, так как она доступна на протяжении всей программы.

Вот пример локальной переменной:

def greet(name):
  message = "Hello, " + name + "!"
  print(message)

greet("John")  ## Output: "Hello, John!"
print(message)  ## Output: NameError: name 'message' is not defined

В этом примере переменная message определена внутри функции greet, поэтому это локальная переменная. Функция greet может получить доступ и распечатать переменную message, но она недоступна вне функции. Если вы попытаетесь получить доступ к переменной message вне функции, вы получите NameError, потому что переменная не определена.

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

message = "Hello, world!"

def greet():
  global message
  message = "Hello, Python!"
  print(message)

greet()  ## Output: "Hello, Python!"
print(message)  ## Output: "Hello, Python!"

В этом примере функция greet использует ключевое слово global для изменения глобальной переменной message. Функция greet выводит измененное значение message, и значение message также изменяется вне функции.

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

Использование функции в качестве аргумента для другой функции

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

def greet(name):
  print("Hello, " + name + "!")

def call(func, args):
  for arg in args:
    func(arg)

names = ["John", "Jane", "Bob"]
call(greet, names)  ## Output: "Hello, John!", "Hello, Jane!", "Hello, Bob!"

В этом примере функция call принимает два аргумента: функцию func и список аргументов args. Она вызывает функцию func с каждым элементом списка args в качестве аргумента.

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

def square(x):
  return x ** 2

def apply(func, numbers):
  result = []
  for number in numbers:
    result.append(func(number))
  return result

numbers = [1, 2, 3, 4, 5]
squared_numbers = apply(square, numbers)
print(squared_numbers)  ## Output: [1, 4, 9, 16, 25]

Этот шаг может быть немного сложным. Не беспокойтесь, если не можете его решить. Вы можете пропустить его и вернуться к нему позже.

Резюме

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

  1. Функции в Python - это блоки кода, которые можно определять, вызывать и повторно использовать.
  2. Функцию можно определить с использованием ключевого слова def, за которым следует имя функции и аргументы.
  3. Тело функции должно быть с отступом, и можно использовать ключевое слово return для возврата значения из функции.
  4. Аргументы функции можно задавать с использованием "именованных аргументов", которые позволяют указать имя аргумента и его значение при вызове функции.
  5. Синтаксис *args можно использовать для определения функции, которая может принимать переменное количество неименованных аргументов, а синтаксис **kwargs - для определения функции, которая может принимать переменное количество именованных аргументов.
  6. Ключевое слово lambda можно использовать для создания анонимных функций, которые определяются и вызываются в одну строку кода.
  7. В Python переменные, определяемые внутри функции, локальны для этой функции и доступны только внутри нее. Переменные, определяемые вне функции, являются глобальными и доступны на протяжении всей программы.
  8. Как правило, лучше избегать использования глобальных переменных и передавать переменные в функции в качестве аргументов и возвращать их в качестве результатов вместо этого.