[Перевод] Аналоги в Python и JavaScript. Часть четвертая
Четвертая часть серии статей про аналоги в Python и JavaScript.
В этой части: аргументы функций, создание и работа с классами, наследование, геттеры-сеттеры и свойства класса.
Краткое содержание предыдущих частей:
- Часть первая: приведение к типу, тернарный оператор, доступ к свойству по имени свойства, словари, списки, строки, конкатенация строк.
- Часть вторая: JSON, регулярки, ошибки-исключения
- Часть третья: современные Python и JS: строковые шаблоны (f-строки), распаковка списков, лямбда-функции, итерации по спискам, генераторы, множества.
Аргументы функций
У Питона обширный инструментарий для работы с аргументами функций — есть значения по умолчанию, переменное число позиционных и именованных аргументов (*args
и **kwargs
).
Когда вы передаете значение в функцию, вы можете указать имя аргумента которому это значение будет передано. В JS тоже существует такая возможность.
Значения по умолчанию для аргументов функций могут быть определены в Питоне:
from pprint import pprint
def report(post_id, reason='not-relevant'):
pprint({'post_id': post_id, 'reason': reason})
report(42)
report(post_id=24, reason='spam')
В JS аналогично:
function report(post_id, reason='not-relevant') {
console.log({post_id: post_id, reason: reason});
}
report(42);
report(post_id=24, reason='spam');
Позиционные аргументы в Питоне могут быть обработаны используя оператор *
:
from pprint import pprint
def add_tags(post_id, *tags):
pprint({'post_id': post_id, 'tags': tags})
add_tags(42, 'python', 'javascript', 'django')
В JS обработка позиционных аргументов происходит при помощи оператора ...
:
function add_tags(post_id, ...tags) {
console.log({post_id: post_id, tags: tags});
}
add_tags(42, 'python', 'javascript', 'django');
Именованные аргументы часто применяются в Питоне когда необходимо передавать изменяемое число аргументов:
from pprint import pprint
def create_post(**options):
pprint(options)
create_post(
title='Hello, World!',
content='This is our first post.',
is_published=True,
)
create_post(
title='Hello again!',
content='This is our second post.',
)
Передача множества именованных аргументов в JS реализуется с помощью словаря (options
в данном примере):
function create_post(options) {
console.log(options);
}
create_post({
'title': 'Hello, World!',
'content': 'This is our first post.',
'is_published': true
});
create_post({
'title': 'Hello again!',
'content': 'This is our second post.'
});
Классы и наследование
Питон — объектно-ориентированный язык. JS начиная с ECMAScript 6 также позволяет писать объектно-ориентированный код без всяких уловок и синтаксических оборотов.
Питон. Создаем класс, конструктор и метод для текстового представления объекта:
class Post(object):
def __init__(self, id, title):
self.id = id
self.title = title
def __str__(self):
return self.title
post = Post(42, 'Hello, World!')
isinstance(post, Post) == True
print(post) # Hello, World!
Аналогичные действия на JS:
class Post {
constructor (id, title) {
this.id = id;
this.title = title;
}
toString() {
return this.title;
}
}
post = new Post(42, 'Hello, World!');
post instanceof Post === true;
console.log(post.toString()); // Hello, World!
Создадим два класса Article
и Link
в Питоне, которые будут наследоваться от класса Post
. Можно заметить, что мы используем ключевое слово super
для доступа к методам базового класса Post
:
class Article(Post):
def __init__(self, id, title, content):
super(Article, self).__init__(id, title)
self.content = content
class Link(Post):
def __init__(self, id, title, url):
super(Link, self).__init__(id, title)
self.url = url
def __str__(self):
return '{} ({})'.format(
super(Link, self).__str__(),
self.url,
)
article = Article(1, 'Hello, World!', 'This is my first article.')
link = Link(2, 'DjangoTricks', 'https://djangotricks.blogspot.com')
isinstance(article, Post) == True
isinstance(link, Post) == True
print(link)
# DjangoTricks (https://djangotricks.blogspot.com)
То же самое в JS:
class Article extends Post {
constructor (id, title, content) {
super(id, title);
this.content = content;
}
}
class Link extends Post {
constructor (id, title, url) {
super(id, title);
this.url = url;
}
toString() {
return super.toString() + ' (' + this.url + ')';
}
}
article = new Article(1, 'Hello, World!', 'This is my first article.');
link = new Link(2, 'DjangoTricks', 'https://djangotricks.blogspot.com');
article instanceof Post === true;
link instanceof Post === true;
console.log(link.toString());
// DjangoTricks (https://djangotricks.blogspot.com)
Свойства класса: геттеры и сеттеры.
В объектно-ориентированном программировании у классов есть атрибуты, методы и свойства. Свойства — это смесь атрибутов и методов. Вы можете обращаться со свойствами как с атрибутами, но где-то внутри они вызывают специальные методы называемые геттерами и сеттерами (getters/setters) для специфической обработки данных.
В данном примере на Питоне показан базовый способ описания геттера и сеттера для свойства slug
с помощью декораторов:
class Post(object):
def __init__(self, id, title):
self.id = id
self.title = title
self._slug = ''
@property
def slug(self):
return self._slug
@slug.setter
def slug(self, value):
self._slug = value
post = new Post(1, 'Hello, World!')
post.slug = 'hello-world'
print(post.slug)
В JS геттер и сеттер для свойства slug
могут быть описаны как:
class Post {
constructor (id, title) {
this.id = id;
this.title = title;
this._slug = '';
}
set slug(value) {
this._slug = value;
}
get slug() {
return this._slug;
}
}
post = new Post(1, 'Hello, World!');
post.slug = 'hello-world';
console.log(post.slug);
Выводы
- В обоих языках можно описать дефолтные значения у аргументов функций.
- В обоих языках можно передавать в функцию произвольное число именованных или позиционных аргументов.
- Оба языка поддерживают объектно-ориетированную парадигму программирования.
Ну, и напоследок автор оригинального поста предлагает купить у него пдфку с цветными шпаргалками по питону и джаваскрипту за пятнадцать баксов.
Распечатать и повесить на стену или сделать бумажный самолетик — решать вам!