Как вызвать функцию в Python?
Как известно, функции — это блоки инструкций, предназначенные для выполнения определенных задач в программировании. Функции позволяют разбивать большие фрагменты кода на более мелкие отрезки или модули. Позже их можно вызывать отовсюду. Это позволяет повторно использовать определенные части программы и избегать повторений. Функции можно определять внутри классов, модулей, вложенных функций и так далее.
Основные особенности функций в Python:
- Используются чтобы избегать повторений в коде,
- Используются для разделения кода на мелкие модули
- Позволяют скрывать код и создавать ясность для понимания модулей,
- Позволяют повторно использовать код и сохранять память,
- Код из функции можно выполнить только по ее имени,
- Простой синтаксис: def имя_функции(параметры): .
- Для объявления функции в Python используется ключевое слово def .
- Название функции должно начинаться с символа латинского алфавита в любом регистре или нижнего подчеркивания.
- В каждой функции есть двоеточие и отступ, после которого записывается сам код программы.
- Зарезервированные ключевые слова не могут использоваться в качестве названия функции.
- Функция может содержать несколько параметров или не иметь их совсем.
Создание функции в Python
Для создания нужно написать ключевое слово def . Синтаксис следующий:
def function_name(): # логика функции return result # возврат значения
Создадим и вызовем реальную функцию в Python:
Добавление функций в классы Python
Классы в Python могут создаваться просто как коллекции функций. Функции можно определить внутри класса обычным образом, так же как и внутри любой программы. А вот для вызова такой функции нужно действовать через данный класс.
От редакции Pythonist: предлагаем также почитать статьи «Классы в Python» и «Переменные класса и экземпляра в Python».
Приведенный ниже пример класса с именем Greetings принимает имя и возвращает приветствие человеку, вызывающему этот класс.
class Greetings: def good_morning(name): print(f'Good morning ') def good_afternoon(name): print(f'Good afternoon ') def good_evening(name): print(f'Good evening ') Greetings.good_afternoon('John') Greetings.good_morning('Peter') Greetings.good_evening('Jane')
Good afternoon John Good morning Peter Good evening Jane
Распространенная ошибка
Пока данный класс ведет себя так, как мы и планировали. Но давайте теперь добавим в него магический метод __init__ .
class Greetings: def __init__(self): pass def good_morning(name): print(f'Good morning ') def good_afternoon(name): print(f'Good afternoon ') def good_evening(name): print(f'Good evening ') g = Greetings()
Мы также создали экземпляр класса Greeting и поместили его в переменную g . Если мы попытаемся вызвать функцию класса как в прошлый раз, только через экземпляр класса, то получим следующую ошибку:
g.good_afternoon('John') # Результат: # TypeError: good_afternoon() takes 1 positional argument but 2 were given
Может быть не вполне понятно, что сейчас произошло. Возвращенная выше ошибка TypeError сообщает, что мы передали функции 2 аргумента вместо одного. А с виду кажется, что был передан только один аргумент. Чтобы понять, что произошло, давайте попробуем вызвать нашу функцию вообще без аргумента:
g.good_afternoon() # Результат: # Good afternoon
Что же тут происходит?
Когда мы создаем экземпляр класса, то первым аргументом, передаваемым функции, является сам этот экземпляр. Таким образом, причина, по которой мы получаем ошибку TypeError, заключается в том, что Python считывает функцию g.good_afternoon(‘John’) как g.good_afternoon(g, ‘John’) . Это может показаться запутанным, но в следующих секциях мы разберем, почему такое происходит.
Методы экземпляров класса
Рассмотрим новый пример класса под названием Student , который принимает в качестве параметров имя, фамилию, возраст и специальность.
class Student: def __init__(self, first, last, age, major): self.first = first self.last = last self.age = age self.major = major def profile(self): print(f"Student name ") print(f"Student age: ") print(f"Major: ") s = Student('Sally' , 'Harris', 20, 'Biology') s.profile()
Student name Sally Harris Student age: 20 Major: Biology
При определении методов экземпляра мы должны передавать в качестве первого аргумента ключевое слово self . Это решает проблему передачи экземпляра класса функциям в качестве первого аргумента.
Давайте создадим текущий класс и добавим функциональность регистрации, чтобы показать способность методов экземпляра класса взаимодействовать с атрибутами.
class Student: def __init__(self, first, last, age, major): self.first = first self.last = last self.age = age self.major = major self.courses = [] def profile(self): print(f"Student name ") print(f"Student age: ") print(f"Major: ") def enrol(self, course): self.courses.append(course) print(f"enrolled in ") def show_courses(self): print(f" is taking the following courses") for course in self.courses: print(course) s = Student('Sally' , 'Harris', 20, 'Biology') s.enrol('Biochemistry I') # enrolled Sally in Biochemistry I s.enrol('Literature') # enrolled Sally in Literature s.enrol('Mathematics') # enrolled Sally in Mathematics s.show_courses() # SallyHarris is taking the following courses # Biochemistry I # Literature # Mathematics
Все вышеперечисленные методы были привязаны к экземпляру класса Student , который мы сохранили в переменную s . Мы можем проверить это, используя ключевое слово dir для нашего экземпляра класса, чтобы увидеть все атрибуты и методы, привязанные к нему.
dir(s) # Результат: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'courses', 'enrol', 'first', 'last', 'major', 'profile', 'show_courses']
В рамках класса мы можем сочетать функции, привязанные к экземплярам класса и обычные функции, которые мы привели в начале данной статьи. Давайте ниже добавим функцию, которая будет выводить на экран текущий учебный год.
import datetime as dt class Student: def __init__(self, first, last, age, major): self.first = first self.last = last self.age = age self.major = major self.courses = [] def profile(self): print(f"Student name ") print(f"Student age: ") print(f"Major: ") def enrol(self, course): self.courses.append(course) print(f"enrolled in ") def show_courses(self): print(f" is taking the following courses") for course in self.courses: print(course) def academic_year(): now = dt.datetime.now() s = now.year, now.year -1 print(f"Current academic year is < str(s[0]) + '/' + str(s[1]) >")
Однако мы все равно получим ошибку, если попытаемся вызвать эту новую функцию из экземпляра класса, так как вызов методов/функций из экземпляров класса всегда передает сам экземпляр класса в качестве первого аргумента. Таким образом, если мы хотим вызвать функцию academic_year() , это можно сделать это следующим образом:
Student.academic_year() # Результат: Current academic year is 2020/2019
Заключение
При вызове функции из класса используется синтаксис ClassName.FunctionName() .
При вызове функции, привязанной к экземпляру класса, первым аргументом, передаваемым функции, является сам экземпляр класса. Такие функции также называют методами.
Чтобы метод правильно работал, мы должны при его написании в качестве первого аргумента указать ключевое слово self .
Данные методы дают нам возможность взаимодействовать с атрибутами, связанными с экземплярами класса.