Лекция 2. : Переменные, константы и базовые типы данных
1. Введение
На прошлой лекции мы познакомились с языком Swift, установили toolchain на Linux и написали первую программу. Сегодня разберём фундамент любой программы — переменные, константы и систему типов. Именно здесь начинаются ключевые отличия Swift от Python: строгая статическая типизация, разделение на изменяемые и неизменяемые привязки и отсутствие неявных преобразований.
Все примеры можно запускать в REPL (swift) или компиляцией файла (swiftc main.swift -o main && ./main).
2. var и let — изменяемость и неизменяемость
var— переменная, значение можно изменять.let— константа, значение задаётся один раз.
var currentTemperature = 23.5currentTemperature = 25.0 // ✅ допустимо
let maxTemperature = 45.0// maxTemperature = 50.0 // ❌ ошибка компиляцииСравнение с Python
# Python — нет встроенного механизма константMAX_TEMPERATURE = 45.0 # соглашение, не ограничениеMAX_TEMPERATURE = 50.0 # Python не запрещаетВ Swift неизменяемость let — гарантия компилятора, а не соглашение. Рекомендуется по умолчанию использовать let и переходить на var только при необходимости. Компилятор даже выдаёт предупреждение, если var ни разу не изменяется.
3. Базовые типы данных
3.1. Целые числа — Int
На 64-битных платформах (включая современный Linux) Int — 64-битное значение со знаком.
let population: Int = 7_900_000_000 // подчёркивания для читаемостиlet negativeValue = -42 // тип выведен как IntТакже доступны Int8, Int16, Int32, Int64 и беззнаковые UInt8…UInt64.
3.2. Числа с плавающей точкой — Double и Float
Double— 64 бит, ~15 значащих цифр. Рекомендуется по умолчанию.Float— 32 бита, ~6 значащих цифр.
let pi: Double = 3.141592653589793let gravity = 9.81 // дробный литерал → Double по умолчанию3.3. Логический тип — Bool
let isLinux: Bool = truelet isComplete = falseВ отличие от Python, Swift не допускает if 1: или if "hello"::
let number = 1// if number { ... } // ❌ Int не является Boolif number != 0 { print("Не ноль") } // ✅3.4. Строки — String и символы — Character
let greeting: String = "Привет, Swift!"let letter: Character = "A" // тип указан явноlet emoji: Character = "🐧"
// let c = "A" // без аннотации это String, не Character4. Вывод типов и явная аннотация
Swift определяет тип по присвоенному значению (type inference):
let age = 25 // Intlet height = 1.78 // Doublelet name = "Алексей" // StringЯвная аннотация нужна, когда требуется конкретный тип или переменная объявляется без значения:
let temperature: Float = 36.6 // без аннотации был бы Doublevar result: String // значение присвоится позжеresult = "Готово"Сравнение с Python
# Python — тип динамический, может менятьсяx = 42 # intx = "строка" # теперь str — Python не возражает// Swift — тип фиксируется при объявленииvar x = 42// x = "строка" // ❌ нельзя присвоить String переменной типа Int5. Строгая типизация и Type Safety
Swift — строго типизированный язык: каждое значение имеет конкретный тип, проверяемый при компиляции. Нельзя смешивать типы без явного преобразования.
let a: Int = 10let b: Double = 3.5// let c = a + b // ❌ нельзя сложить Int и Doublelet c = Double(a) + b // ✅ явное преобразование → 13.5# Python — неявное приведениеa = 10b = 3.5c = a + b # ✅ int автоматически → float → 13.5Строгая типизация предотвращает класс ошибок, которые в Python обнаруживаются только при запуске.
6. Преобразование типов
Преобразование всегда явное — через инициализатор целевого типа.
// Числовыеlet intVal: Int = 42let doubleVal = Double(intVal) // 42.0let truncated = Int(3.14) // 3 — дробная часть отбрасывается
// Строки ↔ числаlet year = String(2025) // "2025"
let input = "314"if let parsed = Int(input) { print("Число: \(parsed)") // Число: 314}// Int("hello") вернёт nil, а не выбросит ошибкуВ Python int("hello") выбрасывает ValueError. Swift возвращает nil — более безопасный подход без try/except. Подробнее об Optionals — на лекции 6.
7. Строковая интерполяция
Значения встраиваются в строку через \(выражение):
let language = "Swift"let version = 6print("Мы изучаем \(language) версии \(version)")
let a = 7, b = 3print("\(a) + \(b) = \(a + b)") // 7 + 3 = 10Сравнение с Python
# Python — f-строкиlanguage = "Swift"version = 6print(f"Мы изучаем {language} версии {version}")| Аспект | Swift | Python |
|---|---|---|
| Синтаксис | \(выражение) | {выражение} в f"" |
| Форматирование | String(format:) | {:.2f} |
| Проверка типов | При компиляции | При выполнении |
8. Многострочные строки
Swift поддерживает многострочные строки через тройные кавычки """:
let poem = """ Мой дядя самых честных правил, Когда не в шутку занемог, Он уважать себя заставил И лучше выдумать не мог. """print(poem)Отступ определяется позицией закрывающих """ — общий отступ автоматически удаляется.
В Python тройные кавычки не управляют отступами — для этого нужен textwrap.dedent().
9. Работа со строками
9.1. Конкатенация и основные операции
let fullName = "Иван" + " " + "Петров"
var greeting = "Привет"greeting += ", мир!" // "Привет, мир!"9.2. Длина и символы
let text = "Привет"print(text.count) // 6 — количество видимых символов (графемных кластеров)
let emoji = "👨👩👧👦"print(emoji.count) // 1 — один видимый символprint(emoji.utf8.count) // 25 байт в UTF-8В Python len("👨👩👧👦") вернёт 7 (считает code points). Swift точнее отражает то, что видит пользователь.
9.3. Индексация
Строки в Swift не индексируются целыми числами — символы Unicode имеют переменную длину. Используется String.Index:
let word = "Swift"let first = word[word.startIndex] // "S"let last = word[word.index(before: word.endIndex)] // "t"let third = word[word.index(word.startIndex, offsetBy: 2)] // "i"9.4. Перебор и полезные методы
for char in "Swift" { print(char) // S, w, i, f, t}
let text = " Hello, Swift! "print(text.uppercased()) // " HELLO, SWIFT! "print(text.lowercased()) // " hello, swift! "print(text.contains("Swift")) // trueprint(text.hasPrefix(" He")) // true
let csv = "один,два,три"let parts = csv.split(separator: ",") // ["один", "два", "три"]Для trimmingCharacters(in:) на Linux необходим import Foundation:
import Foundationlet trimmed = text.trimmingCharacters(in: .whitespaces) // "Hello, Swift!"10. Кортежи (Tuples)
Кортежи объединяют несколько значений разных типов в одно составное значение.
let coordinates = (55.7558, 37.6173) // (Double, Double)let city = (name: "Москва", population: 12_600_000) // именованные элементыДоступ к элементам
print(coordinates.0) // 55.7558 — по индексуprint(city.name) // "Москва" — по имениДекомпозиция
let (latitude, longitude) = coordinatesprint("Широта: \(latitude), долгота: \(longitude)")
let (cityName, _) = city // _ — игнорируем ненужноеКортежи как возвращаемые значения
func divide(_ a: Int, by b: Int) -> (quotient: Int, remainder: Int) { return (a / b, a % b)}
let result = divide(17, by: 5)print("Частное: \(result.quotient), остаток: \(result.remainder)")Сравнение с Python
# Pythondef divide(a, b): return a // b, a % b
quotient, remainder = divide(17, 5)Концепция та же, но в Swift кортежи типизированные и элементы могут иметь имена.
11. Type Aliases (typealias)
typealias создаёт альтернативное имя для существующего типа — повышает читаемость без создания нового типа.
typealias Celsius = Doubletypealias Coordinate = (latitude: Double, longitude: Double)
let bodyTemp: Celsius = 36.6let moscow: Coordinate = (latitude: 55.7558, longitude: 37.6173)Сравнение с Python
# Python (typing) — рекомендация, не проверяется интерпретаторомfrom typing import TypeAliasCelsius: TypeAlias = floatВ Swift typealias полностью интегрирован в систему типов компилятора.
12. Сводная таблица: Swift vs Python
| Концепция | Swift | Python |
|---|---|---|
| Целые числа | Int, Int8…Int64 | int (произвольная точность) |
| Дробные числа | Double, Float | float |
| Строки | String | str |
| Символ | Character | str длины 1 |
| Логический тип | Bool (строго) | bool (truthy/falsy) |
| Константа | let (гарантия компилятора) | Соглашение UPPER_CASE |
| Вывод типов | Статический, при компиляции | Динамический, при выполнении |
| Неявное преобразование | Запрещено | Допускается |
| Интерполяция строк | \(expr) | f"{expr}" |
| Кортежи | Типизированные, с именами | Без типизации |
| Псевдонимы типов | typealias | TypeAlias из typing |
13. Практические задания
Задание 1. Переменные и константы
Объявите значения, выбрав let или var:
- Имя пользователя (не меняется)
- Текущий счёт в игре (меняется)
- Число Пи (не меняется)
- Текущая дата в формате строки (меняется)
Скомпилируйте через swiftc и убедитесь, что программа работает.
Задание 2. Преобразование типов
Объявите a: Int = 17 и b: Double = 3.0. Вычислите результат деления a на b (тип Double) и выведите через строковую интерполяцию.
Задание 3. Работа со строками
Создайте строку с полным именем. Выведите: количество символов, первый и последний символ, строку в верхнем регистре, результат проверки contains("ван").
Задание 4. Кортежи
Напишите функцию minMax(array:), возвращающую кортеж (min: Int, max: Int):
func minMax(array: [Int]) -> (min: Int, max: Int) { // ваш код}let result = minMax(array: [3, 1, 7, -2, 5])print("Мин: \(result.min), макс: \(result.max)")// Ожидаемо: Мин: -2, макс: 7Задание 5. Type Alias
Создайте typealias Student = (name: String, age: Int, grade: Double). Напишите функцию, принимающую [Student] и возвращающую средний балл.
14. Вопросы для самопроверки
- Чем
letотличается отvar? Почемуletрекомендуется по умолчанию? - Какой тип выведет компилятор для
3.14? А для42? - Почему
let x: Int = 5; let y: Double = 2.5; let z = x + yне компилируется? - Чем
\(expr)в Swift отличается отf"{expr}"в Python с точки зрения безопасности? - Почему Swift не позволяет
text[0]для доступа к символу строки? - Чем
String.countотличается отlen()на строках с эмодзи? - Что вернёт
Int("hello")и почему это безопаснее, чемint("hello")в Python? - Приведите пример, когда строгая типизация Swift предотвращает ошибку, которая в Python обнаружилась бы только при выполнении.
15. Резюме
letиvar— неизменяемость гарантируется компилятором, а не соглашениями.- Базовые типы (
Int,Double,Float,String,Bool,Character) — полноценные структуры с методами. - Вывод типов позволяет не указывать тип явно, но тип фиксируется при компиляции.
- Строгая типизация исключает неявные преобразования — ошибки обнаруживаются до запуска.
- Строковая интерполяция через
\(...)— удобный и типобезопасный аналог f-строк. - Кортежи — лёгкий способ группировки значений без создания отдельного типа.
typealias— осмысленные имена для существующих типов, повышающие читаемость.
На следующей лекции: операторы, управление потоком выполнения, switch с pattern matching и оператор guard.