Код на салфетке
2.24K subscribers
749 photos
15 videos
2 files
792 links
Канал для тех, кому интересно программирование на Python и не только.

Сайт: https://pressanybutton.ru/
Чат: https://t.iss.one/+Li2vbxfWo0Q4ZDk6
Заметки автора: @writeanynotes

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Аналогия примерно та же, что и с шаблоном кабинета, поскольку посты получаем на этапе представления для автора или пользователя, нет необходимости делать блоки с постами.
Вместо этого мы добавим блоки с кнопками и отображением статуса поста – черновик или опубликован.

В шаблоне user_posts_page.html в удобное место добавляем блок с кнопками:
{% if is_author %}  
<div class="col-3 d-flex text-center">
{% block buttons %}
{% endblock %}
</div>
{% endif %}


И блок со статусом:
{% if is_author %}{% block status %}{% endblock %}{% endif %}



Код шаблона:
Много текста. Код доступен на сайте или в материалах к посту.


Создаём новый файл user_posts_page_author.html, в него прописываем код блоков:
{% extends 'user_app/user_posts_page.html' %}  

{% block buttons %}
<a href="{% url 'user_app:edit_post' pk=post.pk %}" class="btn btn-sm btn-primary my-btn-success w-100 me-1">Редактировать</a>
<a href="{% url 'user_app:delete_post' pk=post.pk %}" class="btn btn-sm btn-secondary my-btn-danger w-100 me-1">Удалить</a>
{% endblock %}

{% block status %}
| {{ post.get_status_display }}
{% endblock %}



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

Файлы к посту, можно получить в боте по коду: 401184

Пост на сайте
Поддержать проект

#Python #Django #Гайды #шаблоны #Представления #dispatch #Декоратор #кабинет_автора
🔥4
👀Как мне повезло с моей командой готовой работать за идею!))
😁7
Всем привет.

Уверен, у многих выдалась непростая неделя. Самое время немножко отдохнуть за просмотром хорошего фильма. Заваривайте чаёк или чего-нибудь покрепче (кому как) и устраивайтесь поудобнее.

Данный фильм подойдёт как для одиночного, так и для семейного просмотра.

Фильм: Создатель
Год: 2023

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

https://www.sspoisk.ru/film/4499408/?utm_referrer=www.google.com

Приятного просмотра. А когда посмотрите - расскажите в комментарии, что вы о нём думаете (без спойлеров) 🙂
🔥2
Что выведет этот код? №3
Вчера мы опубликовали весьма непростую задачу. Правильный ответ стал откровением в том числе и для нашей редакции. Наверняка многие из вас знают Python на достаточном уровне, чтобы понимать lambda-выражения, но часто ли вы используете их в коде? Знаете ли о нюансах их работы?

Об одном из таких нюансов мы и поведаем вам в разборе этой задачи.

В этот раз набралось 27 ответов. Правильно ответили всего 5 человек, это 19% от общего числа ответов. Самым популярным ответом оказался второй, набравший 52%, потому что именно такого результата ожидаешь, смотря в код.

Код задачи:
funcs = [lambda x: x * i for i in range(5)]
print([f(3) for f in funcs])


Всего две строки кода. Давайте разберёмся, что здесь происходит:

В первой строке:
1. Генерируем список из пяти lambda-функций. lambda-функция умножает переданное в неё значение x на i. При этом значения i меняются от 0 до 4 по мере прохождения цикла по результатам работы функции range(5).
2. В переменную funcs помещаем сгенерированный список.

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

Что же тут не так? Почему правильный ответ [12, 12, 12, 12, 12], а не [0, 3, 6, 9, 12]? Ведь переменная i у нас по очереди принимала значения от 0 до 4.

Всё дело в особенностях работы lambda-функций и цикла for.
Так выходит, что lambda-функция не запоминает значение i во время создания первого списка. Она буквально запоминает выражение x * i, а не x * <значение_i>, то есть как будто использует i в качестве заглушки без конкретного значения.

Ещё одна особенность в том, что переменная i после окончания работы цикла for не пропадает в жерновах сборщика мусора. Она остаётся доступной и содержит последнее записанное в нее на момент остановки работы цикла значение. Рассмотрим на примере:

for i in range(5):
continue

print(i)
>>> 4


Переменная i по ходу работы цикла приняла все целочисленные значения от 0 до 4. Когда работа цикла завершилась, в переменной i оказалось записано последнее из них – 4.

Это же и происходит в генераторе второго списка.
Вызывая f(3) вместо:
3 * 0
3 * 1
3 * 2
3 * 3
3 * 4

>>> [0, 3, 6, 9, 12]


Мы получаем:
3 * 4
3 * 4
3 * 4
3 * 4
3 * 4

>>> [12, 12, 12, 12, 12]


Можно ли изменить код таким образом, чтобы получить в результате его работы [0, 3, 6, 9, 12]?

Можно. Всё достаточно просто. Необходимо в аргументы lambda-функции, помимо x, передать ещё и i, установив её в качестве аргумента по умолчанию равного i:
funcs = [lambda x, i=i: x * i for i in range(5)]
print([f(3) for f in funcs])


Таким образом, каждая итерация lambda-функции будет запоминать значение i, поскольку оно теперь передано в аргументах функции.
🔥5🤯5
Django 38.2. Добавление, редактирование, удаление поста
Автор: Иван Ашихмин

В прошлом посте, мы доработали профиль пользователя, превратив его в кабинет автора. Для этого мы написали свой декоратор и расширили шаблон страницы.

В этом посте мы разберёмся, что такое миксины (mixins), для чего они нужны, как применяются и как написать свои.
Изменим имеющееся представление страницы добавления поста, превратив его в базовый класс, от которого унаследуем два представления: добавления и изменения поста.
Также добавим представление и страницу удаления поста.

Начнём с небольшой теории.


Что такое миксины (mixins)?
🔥1
Миксины (mixins) представляют собой специальные классы, которые содержат методы и функциональность для повторного использования в других классах. Они используются для организации кода, обеспечивая переиспользование функциональности между различными классами представлений, моделей или других компонентов Django.

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


Как работают миксины в Django:

Определение миксина:
Миксин - это обычно класс Python, содержащий методы и атрибуты, предназначенные для использования в других классах. Например:
class MyMixin:
def some_method(self):
# Логика метода
pass



Использование миксина:
Для применения миксина к классу необходимо добавить его в список наследования:
from django.views import View


class MyView(MyMixin, View):
def get(self, request):
# Логика представления
return HttpResponse('Hello, World!')


Здесь MyView наследуется от MyMixin и View. Теперь методы из MyMixin доступны в MyView.


Применение миксинов в Django:
- Представления (Views): Миксины могут использоваться для добавления функциональности к представлениям Django, например, для добавления проверок доступа, кэширования или другой логики.
- Модели (Models): Миксины также могут содержать методы для работы с моделями Django, например, для добавления общих методов или свойств к нескольким моделям.
- Формы (Forms): Миксины можно использовать для повторного использования функциональности в формах Django, такой как валидация данных или обработка форм.
- Другие компоненты: Кроме того, миксины можно использовать практически в любом компоненте Django, где требуется повторное использование функциональности.

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


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

В директории приложения user_app создадим файл mixins.py. В нём будем писать наши миксины.


Миксин проверки принадлежности к группе.
Для того, что бы проверять входит ли пользователь в необходимую группу, в данном случае в группу Автор, можно в каждом представлении прописывать метод dispatch() с проверкой. Чтобы избежать дублирования кода, мы напишем миксин с проверкой.

Создадим класс PermissionGroupRequiredMixin.

В нём пропишем поле group_required и присвоим ему значение None. Это поле с названием необходимой группы будем прописывать в представлении.

Затем создадим метод dispatch(). В методе проверяем, входит ли пользователь в указанную группу, то мы вызываем dispatch() из класса представления. Иначе поднимаем ошибку 403 HttpResponseForbidden с сообщением об отсутствии доступа.


Код миксина:
from django.http import HttpResponseForbidden


class PermissionGroupRequiredMixin:
group_required = None

def dispatch(self, request, *args, **kwargs):
if request.user.groups.filter(name=self.group_required).exists():
return super().dispatch(request, *args, **kwargs)
else:
raise HttpResponseForbidden("Вы не имеете доступа к этой странице.")
🔥1
Как видим, достаточно просто.


Миксин проверки автора поста.
Для представлений редактирования и удаления поста, необходима проверка того, что автор поста и текущий пользователь - один человек.

Создадим класс PermissionSameAuthorMixin.

Код будет такой же, как и предыдущий.
Полей у миксина не будет, а в методе dispatch() изменим проверку.


Код миксина:
from django.http import HttpResponseForbidden


class PermissionSameAuthorMixin:

def dispatch(self, request, *args, **kwargs):
if request.user self.get_object().author:
return super().dispatch(request, *args, **kwargs)
else:
raise HttpResponseForbidden("Вы не имеете доступа к этой странице.")



Представления.
В директории приложения user_app откроем файл views.py.

В посте Django 36. Добавление постов пользователем мы написали следующее представление для страницы добавления поста:
class AddPostByAuthorView(UserPassesTestMixin, CreateView):
template_name = 'user_app/add_post.html'
form_class = forms.AddPostByAuthorForm
model = PostModel

def test_func(self):
return self.request.user.groups.filter(name='Автор').exists()

def get_success_url(self):
return reverse('user_app:user_profile', kwargs={'username': self.request.user.username})

def form_valid(self, form):
form.instance.slug = slugify(form.instance.title)
form.instance.author = self.request.user
return super().form_valid(form)


Мы его изменим, уберём лишнее и создадим два наследуемых класса.


Базовое представление.
Первым делом изменим имя класса на PostByAuthor, убрав все наследования.

К имеющимся полям добавим новое поле group_required со значением необходимой для доступа к представлениям группы. В нашем случае группы Автор.

Удалим метод test_func, так как он нам больше не нужен.

Всё остальное оставляем как есть. Если IDE будет ругаться на некоторые методы, игнорируем. У нас в классе их нет, но они будут в наших классах наследниках.


Код класса:
from django.urls import reverse_lazy
from pytils.translit import slugify

from blog.models import PostModel
from user_app import forms

class PostByAuthor:
template_name = 'user_app/add_post.html'
group_required = 'Автор'
form_class = forms.AddPostByAuthorForm
model = PostModel

def get_success_url(self):
return reverse('user_app:user_profile', kwargs={'username': self.request.user.username})

def form_valid(self, form):
form.instance.slug = slugify(form.instance.title)[:50]
form.instance.author = self.request.user
return super().form_valid(form)



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

Создаём два класса:
- AddPostByAuthorView, унаследованный от PostByAuthor, PermissionGroupRequiredMixin, CreateView.
- EditPostByAuthorView, унаследованный от PostByAuthor, PermissionSameAuthorMixin, UpdateView.
🔥1
В первом классе мы наследуемся от нашего основного класса, миксина проверки принадлежности к группе и встроенного класса CreateView.
Во втором классе мы также наследуемся от основного класса, миксина, проверяющего идентичность автора поста и пользователя, и от стандартного UpdateView.

В обоих классах добавляем единственное поле extra_context, в котором прописываем заголовок страницы. Это всё, что будет в двух представлениях.


Код представлений:
from django.views.generic import CreateView, UpdateView

from user_app.mixins import PermissionSameAuthorMixin, PermissionGroupRequiredMixin


class AddPostByAuthorView(PostByAuthor, PermissionGroupRequiredMixin, CreateView):
extra_context = {'title': 'Добавление поста'}


class EditPostByAuthorView(PostByAuthor, PermissionSameAuthorMixin, UpdateView):
extra_context = {'title': 'Изменить пост'}



Представление страницы удаления поста.
Для страницы удаления поста мы напишем отдельное представление.

Создадим класс DeletePostByAuthorView, унаследованный от PermissionSameAuthorMixin и DeleteView.

Прописываем четыре поля:
- template_name - шаблон страницы.
- model - модель поста.
- group_required - требуемая группа для доступа к странице.
- extra_context - дополнительные данные передаваемые в шаблон. В нашем случае заголовок страницы.

Также переопределяем метод get_success_url(), возвращая на страницу профиля. Он такой же как и в представлениях выше.


Код представления:
from django.views.generic import DeleteView
from django.urls import reverse_lazy

from blog.models import PostModel
from user_app.mixins import PermissionSameAuthorMixin


class DeletePostByAuthorView(PermissionSameAuthorMixin, DeleteView):
template_name = 'user_app/delete_post_confirm.html'
model = PostModel
group_required = 'Автор'
extra_context = {'title': 'Удалить пост?'}

def get_success_url(self):
return reverse_lazy('user_app:user_profile', kwargs={'username': self.request.user.username})



Шаблон страницы удаления поста.
Создадим файл delete_post_confirm.html в директории с шаблонами.

В шаблоне прописываем форму с двумя кнопками: "подтвердить удаление поста" и "вернуться в профиль".


Код шаблона:
{% extends 'blog/base.html' %}  
{% block title %}{{ title }}{% endblock %}

{% block content %}
&lt;div class="form-section container mt-3"&gt;
&lt;h2&gt;Удаление поста {{ object }}&lt;/h2&gt;
&lt;p&gt;Вы действительно хотите удалить этот пост?&lt;/p&gt;
&lt;form method="POST"&gt;
{% csrf_token %}
&lt;button class="btn btn-secondary my-btn-danger me-2" type="submit"&gt;Да, удалить&lt;/button&gt;
&lt;a href="{% url 'user_app:user_profile' username=request.user.username %}" class="btn btn-primary my-btn-success"&gt;Отмена&lt;/a&gt;
&lt;/form&gt; &lt;/div&gt;{% endblock %}



URL-паттерны.
Осталось добавить URL-паттерны представлений.
Кнопки в кабинете автора мы добавили в прошлом посте.

Откроем файл urls.py в директории приложения user_app и добавим следующие строки в список urlpatterns:
🔥2
path('post/add_post/', views.AddPostByAuthorView.as_view(), name='add_post'),  
path('post/edit_post/&lt;int:pk&gt;', views.EditPostByAuthorView.as_view(), name='edit_post'),
path('post/delete_post/&lt;int:pk&gt;', views.DeletePostByAuthorView.as_view(), name='delete_post'),



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

Кроме того, мы ещё раз попробовали создать базовый класс и сделать на его основе представления. Мы сделали один большой класс и два буквально двустрочных. Если бы мы не сделали базовый класс, у нас вместо трёх, было бы два представления, однако оба были бы идентичными.

Файлы к посту, можно получить в боте по коду: 949621

Пост на сайте
Поддержать проект

#Python #Django #Гайды #шаблоны #представления #классы #наследование #Миксины #Mixin #группы
🔥5
Проекту "Код на салфетке" исполняется 6 месяцев!
Автор: Иван Ашихмин

Приветствую.

Сегодня каналу исполняется 6 месяцев!
Это большое событие для меня лично.

Начиная канал, я и не подозревал, что буду вести его не один, что в чате соберётся своё сообщество активных и интересных людей, что на канал подпишется аж 310 человек.

Благодарю всех подписчиков и причастных к каналу людей за помощь, поддержку и критику. Без вас этого всего бы не было.

Нельзя обойти стороной и тех, кто помогает с каналом и пишет посты:
- Спасибо Кристине Большаковой, за веру, поддержку, советы и идеи.
- Спасибо Андрею Лебедеву, за полезную, интересную и так легко читаемую рубрику о тонкостях Python.
- Спасибо Евгению Акопяну, за помощь в дизайне для канала, а так же за разработку нового дизайна для сайта.
- Спасибо Артуру Мурзыеву, моему хорошему другу, который ведёт рубрику пятничного кино, а может и ещё, что-то будет вести 😉.
- И другим причастным, пожелавшим остаться неизвестными, тоже огромное спасибо!
🔥91🤩1
И это только начало. Планов по развитию много, осталось только их воплотить в жизнь.

Особая благодарность поддерживающим проект на Boosty:
- Яковлев Павел
- Сергей Гордиенко
- Юрий Гаврилович
- Кристина
- MSSW

Вы помогаете оплачивать сервер и даёте мотивацию продолжать.

Огромное спасибо!

Пост на сайте
Поддержать проект

#Новости #Код_на_салфетке #пол_года
🔥6
Что? Уже? Пролетел очередной месяц учёбы...

По этому поводу готов очередной отчёт на Pikabu.

https://pikabu.ru/story/obuchenie_semnadtsatyiy_mesyats_10949513


😊Как обычно, с вас лайки)
🔥7
Приветствую, друзья!

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

Фильм: Голодные игры: Баллада о змеях и певчих птицах

Год: 2023

До того как стать деспотичным президентом Панэма, молодой Кориолан Сноу был последней надеждой своего увядающего рода — некогда великой династии, впавшей в немилость послевоенного Капитолия. Накануне десятых ежегодных Голодных игр Сноу назначают наставником Люси Грей Бэйрд — трибута дистрикта 12. Постепенно девушка привлекает все больше внимание Панэма, становясь фавориткой грядущего соревнования. Начинается гонка со временем, которая покажет, кто певчая птица, а кто — змея.

Всем приятного просмотра и делимся своим мнением в комментариях

https://www.sspoisk.ru/film/1289334/?utm_referrer=www.google.com
🔥2🤮1
Что выведет этот код? №4
Вчерашняя задача была проще предыдущих, но, как нам представляется, получилась при этом не менее интересной. Она напоминает самую первую задачу из рубрики "Что выведет данный код?" и направлена на внимательность и понимание областей видимости в Python.

В викторине приняло участие 26 человек. Верный ответ оказался одним из двух наиболее популярных: 34% (9 человек) ответили, что код выведет "UnboundLocalError" - и это правильно! Столько же человек посчитало, что код выведет "Осталось конфет: 4". Увы, это неверно, и сейчас мы подробно разберём, почему...

Давайте же разберём эту задачу.

Код задачи:

candies = 5


def deco(func):
def wrapper():
candies -= 1
func()

return wrapper


@deco
def print_candies():
print(f'Осталось конфет: {candies}.')


print_candies()


В самом начале объявлена переменная candies со значением 5.

Далее прописывается простейший декоратор deco. Если устройство декоратора вызывает вопросы, подробно эту тему мы рассматривали в посте "[Декораторы в питоне](https://pressanybutton.ru/post/nyuansy-python/dekoratory-v-pitone/?utm_source=telegram&utm_medium=channel&utm_campaign=post)". Сейчас же подробное описание пока пропустим.

Затем объявляем задекорированную функцию print_candies(), выводящую на экран количество конфет в переменной candies.

В самом конце вызываем print_candies(), чтобы запустить весь процесс.

Вернёмся к декоратору deco. В нём мы уменьшаем значение переменной candies на единицу и вызываем задекорированную функцию print_candies().

И что же мы получаем в результате работы? Ошибку!


Почему ошибка?
Всё дело в области видимости, к которой относится переменная candies. Переменная из верхней строчки кода (в которой лежит 5 конфет) существует в глобальном контексте: она определена вне любой из функций программы. В принципе к ней можно обратиться из любой функции, но только чтобы считать ее значение. Однако в функции wrapper() внутри декоратора мы не просто считываем значение глобальной переменной candies, но и пытаемся изменить его, уменьшив на единицу, а это уже запрещенный приём. Изменять внутри функции можно значение только тех переменных, которые существуют в их локальной области видимости. В противном случае нас ожидает исключение UnboundLocalError.

Чтобы глобальная переменная candies стала доступна для изменения внутри функции wrapper(), необходимо объявить её глобальной при помощи ключевого слова global:
candies = 5


def deco(func):
def wrapper():
global candies
candies -= 1
func()

return wrapper


@deco
def print_candies():
print(f'Осталось конфет: {candies}.')


print_candies()
🔥4
Сравнение типизации Python и C
Автор: Arduinum628

Всем доброго дня! На канале начинается новая рубрика - "Сравнение языка Python 3 и C". Чем отличается высокоуровневый Python от низкоуровневого C? Что такое компилятор? Как работает интерпретатор Python? Как подружить Python и C? Как пк взаимодействует с низкоуровневыми языками? На эти и другие вопросы, связанные с данной темой, ответит новая рубрика. Все примеры я буду писать и запускать в операционной системе Kubuntu. Kubuntu - производный от Ubuntu дистрибутив Linux. Приготовьтесь к открытиям и экспериментам. Погружение в низкий уровень начинается...

Сравнение типизации

Нам известно, что Python имеет динамическую типизацию. Это означает, что типы переменных определяются во время выполнения программы и могут измениться на лету во время выполнения программы. Это даёт некоторую гибкость использования данных в Python.
🔥4
age = 20
print('Возраст пользователя ' + str(age) + 'лет')


В примере выше мы преобразуем данные переменной age в строку, складываем строку и выводим результат. Как же обстоят дела с типизацией в С? В языке С типизация является статической. Это значит, что типы переменных будут определяться на этапе компиляции. Что же такое, собственно, компиляция? Компиляция - это процесс преобразования исходного кода программы в машинный код или байт-код. Этот процесс выполняет программа-компилятор. В этой статье я покажу вам, как запускать С код. Однако более подробно про компиляцию и компилятор мы поговорим в следующих статьях, а пока давайте вернёмся к типизации языка С. К сожалению, в С нет возможности преобразования типа на лету, но есть удобный способ форматирования данных для вывода в консоль.

int age = 20;
printf('Возраст пользователя %d лет', age);


В данном примере мы строго указываем тип при создании переменной, а также указываем спецификатор формата %d (целое число int типа), который укажет, какой тип данных ожидать при выводе. Функция printf выведет данные в консоль. Я думаю, читатель заметит схожесть вставки данных из переменных с оператором % из Python для форматирования строк. Давайте посмотрим как это выглядит в Python.

age: int = 20
print('Возраст пользователя %d лет' % age)


Главным отличием будет то, что в Python при форматировании строки % произойдёт преобразование типа int в str на лету, в то время как в примере с языком С форматирование происходит для вывода в консоль и при этом тип данных при выводе не меняется. Также, начиная с Python 3.6 и выше, можно указать типы переменных в синтаксисе, если это необходимо для улучшения читаемости кода (как в примере выше). В версии Python 3.5 это делалось в комментарии age = 20 # type: int. Это называется "аннотация типов". После этого вы сможете изменить тип переменной, но некоторые IDE будут подсвечивать вам подсказки при неправильной работе с типом данных. Например, PyCharm поддерживает аннотации. На работу программы это влиять не будет, типизация в Python по-прежнему будет динамической. Однако это будет работать на уровне соглашения между разработчиками. Если в переменной указан тип int, значит, разработчики не будут менять тип данных для переменной.

Оба вида типизации обладают своими преимуществами и недостатками. Преимущество динамической типизации в Python над статической в С том, что она позволяет писать код быстрее и делает его более гибким. Почему так?Преобразование типов данных происходит на лету, а сам синтаксис получается короче. Соответственно, C не такой гибкий и быстрый в написании кода. Преимущество статической типизации С над динамической Python в том, что при компиляции программы мы видим все ошибки в коде сразу. Также статическая типизация выигрывает у динамической типизации в скорости выполнения программы из-за того, что при динамической типизации приходится тратить дополнительное время для проверки типов во время выполнения программы.

Собственно говоря, я упоминал о выводе данных в консоль, но как вывести результат нашей программы, написанной на С? Достаточно ли этих двух строк для работы программы?

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

В terminal

$ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. &amp;nbsp;There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
🔥2👍1
Вывод выше показывает, что у нас установлена версия компилятора 11.4.0. Это означает, что мы можем приступить к сборке программы и увидеть результат? Ответ "да", но только если мы добавим дополнительные строки в нашу программу.

#include &lt;stdio.h&gt;
int main(){
int age = 20;
printf('Возраст пользователя %d лет', age);
return 0;
}


Итак, что мы добавили за строки? Строка #include &lt;stdio.h&gt; подключает стандартную библиотеку для С, в которой содержится функционал для ввода/вывода в том числе функция printf, которую мы используем в нашем коде. Функция main является обязательной и в случае успеха возвращает 0 по умолчанию (С99 и новее). Также можно прописывать return 0, что не будет ошибкой, особенно для более старых версий. Я решил оставить вариант с return 0, так как он более универсален. Наш файл с кодом мы должны сохранить в файл с расширением .c. Пусть это будет age_print.c.

Давайте с вами скомпилируем программу для получения исполняемого файла. Для этого нам нужно, находясь в terminal, перейти в папку с нашим файлом age_print.c и дать команду компиляции.

В terminal

$ gcc age_print.c -o age_print
age_print.c: In function ‘main’:
age_print.c:5:12: warning: character constant too long for its type
5 | printf('Возраст пользователя %d лет', age);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
age_print.c:5:12: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [-Wint-conversion]
5 | printf('Возраст пользователя %d лет', age);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| int
In file included from age_print.c:1:
/usr/include/stdio.h:356:43: note: expected ‘const char * restrict’ but argument is of type ‘int’
356 | extern int printf (const char *__restrict __format, ...);


Рассмотрим команду подробнее. Мы говорим gcc компилятору скомпилировать исходный код с именем age_print.c и создать исполняемый файл age_print. На название файла указывает флаг -o. Под командой в terminal мы видим вывод. Что же это за вывод такой? Это предупреждения отладчика. В нашем случае я специально указал не те кавычки, чтобы показать вам, что произойдёт, когда показываются предупреждения при компиляции. Более подробно о компиляции вы узнаете в следующих статьях. При замене на "" кавычки эти предупреждения пропадут. Исправим наш код и добавим перенос \n строки для более красивого вывода результата работы программы.

#include &lt;stdio.h&gt;
int main(){
int age = 20;
printf("Возраст пользователя %d лет\n", age);
return 0;
}


Повторно запустим команду выше и посмотрим на результат. При успешной компиляции мы не видим никакого сообщения в terminal. Но мы видим, что рядом с нашим age_print.c появился исполняемый файл age_print. Файл появился в результате успешной компиляции без ошибок.

В terminal

$ ./age_print
Возраст пользователя 20 лет


Поздравляю, мы написали нашу первую программу на C, скомпилировали и запустили её. Моя рубрика сравнивает Python и C, и, раз я затронул в этой статье тему компиляции, в следующей статье я раскрою тему выполнения программ на обоих языках. Вы узнаете, чем компилятор С отличается от интерпретатора Python. Дальше будет ещё интереснее :)

Заключение
1. При объявлении переменной в С мы явно указываем тип в отличие от Python, но зато в Python есть аннотация для типов данных;
2. В отличие от Python язык С не способен преобразовывать типы данных на лету для вставки данных, но есть удобный способ форматирования данных для вывода в консоль;
3. Язык с динамической типизацией быстрее в разработке и код более гибкий;
🔥31