summaryrefslogtreecommitdiffhomepage
path: root/ru-ru
diff options
context:
space:
mode:
Diffstat (limited to 'ru-ru')
-rw-r--r--ru-ru/coffeescript-ru.html.markdown104
-rw-r--r--ru-ru/go-ru.html.markdown44
-rw-r--r--ru-ru/haskell-ru.html.markdown546
-rw-r--r--ru-ru/julia-ru.html.markdown2
-rw-r--r--ru-ru/markdown-ru.html.markdown279
-rw-r--r--ru-ru/objective-c-ru.html.markdown2
-rw-r--r--ru-ru/php-ru.html.markdown2
-rw-r--r--ru-ru/python-ru.html.markdown266
-rw-r--r--ru-ru/python3-ru.html.markdown630
9 files changed, 1770 insertions, 105 deletions
diff --git a/ru-ru/coffeescript-ru.html.markdown b/ru-ru/coffeescript-ru.html.markdown
new file mode 100644
index 00000000..f8416f38
--- /dev/null
+++ b/ru-ru/coffeescript-ru.html.markdown
@@ -0,0 +1,104 @@
+---
+language: coffeescript
+contributors:
+ - ["Tenor Biel", "http://github.com/L8D"]
+ - ["Xavier Yao", "http://github.com/xavieryao"]
+translators:
+ - ["asaskevich", "http://github.com/asaskevich"]
+filename: learncoffee-ru.coffee
+lang: ru-ru
+---
+
+CoffeeScript - это небольшой язык, который компилируется один-в-один в эквивалентный код на языке JavaScript, а потому он не интерпретируется во время исполнения JavaScript кода.
+Ключевой особенностью CoffeeScript является то, что он пытается создать читабельный, качественно оформленный и плавный JavaScript код, прекрасно работающий в любой среде JavaScript.
+
+Также загляните на официальный сайт [языка](http://coffeescript.org/), где можно найти весьма полное учебное пособие по CoffeeScript.
+
+```coffeescript
+# CoffeeScript - язык хипстеров.
+# Язык использует самое модное из множества современных языков.
+# Эти комментарии по стилю похожи на комментарии Ruby или Python, они используют "решетку" в качестве знака комментария.
+
+###
+Блоки комментариев выделяются тремя символами "решетки", в результирующем JavaScript коде они будут преобразованы в '/ * и '* /'.
+
+Перед тем, как идти далее, Вам нужно понимать семантику JavaScript.
+###
+
+# Присвоение:
+number = 42 #=> var number = 42;
+opposite = true #=> var opposite = true;
+
+# Условия:
+number = -42 if opposite #=> if(opposite) { number = -42; }
+
+# Функции:
+square = (x) -> x * x #=> var square = function(x) { return x * x; }
+
+fill = (container, liquid = "coffee") ->
+ "Заполняем #{container} жидкостью #{liquid}..."
+#=>var fill;
+#
+#fill = function(container, liquid) {
+# if (liquid == null) {
+# liquid = "coffee";
+# }
+# return "Заполняем " + container + " жидкостью " + liquid + "...";
+#};
+
+# Списки и диапазоны:
+list = [1..5] #=> var list = [1, 2, 3, 4, 5];
+
+# Объекты:
+math =
+ root: Math.sqrt
+ square: square
+ cube: (x) -> x * square x
+#=> var math = {
+# "root": Math.sqrt,
+# "square": square,
+# "cube": function(x) { return x * square(x); }
+#}
+
+# Многоточия:
+race = (winner, runners...) ->
+ print winner, runners
+#=>race = function() {
+# var runners, winner;
+# winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+# return print(winner, runners);
+#};
+
+# Проверка на существование объекта:
+alert "Так и знал!" if elvis?
+#=> if(typeof elvis !== "undefined" && elvis !== null) { alert("Так и знал!"); }
+
+# Итерации по массивам:
+cubes = (math.cube num for num in list)
+#=>cubes = (function() {
+# var _i, _len, _results;
+# _results = [];
+# for (_i = 0, _len = list.length; _i < _len; _i++) {
+# num = list[_i];
+# _results.push(math.cube(num));
+# }
+# return _results;
+# })();
+
+foods = ['broccoli', 'spinach', 'chocolate']
+eat food for food in foods when food isnt 'chocolate'
+#=>foods = ['broccoli', 'spinach', 'chocolate'];
+#
+#for (_k = 0, _len2 = foods.length; _k < _len2; _k++) {
+# food = foods[_k];
+# if (food !== 'chocolate') {
+# eat(food);
+# }
+#}
+```
+
+## На почитать
+
+- [Smooth CoffeeScript](http://autotelicum.github.io/Smooth-CoffeeScript/)
+- [CoffeeScript Ristretto](https://leanpub.com/coffeescript-ristretto/read)
+- [CoffeeScript на русском](http://cidocs.ru/coffeescript/)
diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown
index ffda01b7..44a22b45 100644
--- a/ru-ru/go-ru.html.markdown
+++ b/ru-ru/go-ru.html.markdown
@@ -13,11 +13,11 @@ lang: ru-ru
---
Go - это язык общего назначения, целью которого является удобство, простота,
-конкуррентность. Это не тренд в компьютерных науках, а новейший и быстрый
+конкурентность. Это не тренд в компьютерных науках, а новейший и быстрый
способ решать насущные проблемы.
Концепции Go схожи с другими императивными статически типизированными языками.
-Быстро компилируется и быстро исполняется, имеет легкие в понимании конструкции
+Быстро компилируется и быстро исполняется, имеет лёгкие в понимании конструкции
для создания масштабируемых и многопоточных программ.
Может похвастаться отличной стандартной библиотекой и большим комьюнити, полным
@@ -57,7 +57,7 @@ func main() {
func beyondHello() {
var x int // Переменные должны быть объявлены до их использования.
x = 3 // Присвоение значения переменной.
- // Краткое определение := позволяет объявить перменную с автоматической
+ // Краткое определение := позволяет объявить переменную с автоматической
// подстановкой типа из значения.
y := 4
sum, prod := learnMultiple(x, y) // Функция возвращает два значения.
@@ -70,7 +70,7 @@ func learnMultiple(x, y int) (sum, prod int) {
return x + y, x * y // Возврат двух значений.
}
-// Некотрые встроенные типы и литералы.
+// Некоторые встроенные типы и литералы.
func learnTypes() {
// Краткое определение переменной говорит само за себя.
s := "Learn Go!" // Тип string.
@@ -79,7 +79,7 @@ func learnTypes() {
может содержать переносы строк` // Тоже тип данных string
// Символ не из ASCII. Исходный код Go в кодировке UTF-8.
- g := 'Σ' // тип rune, это алиас для типа uint32, содержит символ юникода.
+ g := 'Σ' // тип rune, это алиас для типа int32, содержит символ юникода.
f := 3.14195 // float64, 64-х битное число с плавающей точкой (IEEE-754).
c := 3 + 4i // complex128, внутри себя содержит два float64.
@@ -97,7 +97,7 @@ func learnTypes() {
// Слайсы (slices) имеют динамическую длину. И массивы, и слайсы имеют свои
// преимущества, но слайсы используются гораздо чаще.
- s3 := []int{4, 5, 9} // Сравните с a3. Тут нет троеточия.
+ s3 := []int{4, 5, 9} // Сравните с a3, тут нет троеточия.
s4 := make([]int, 4) // Выделение памяти для слайса из 4-х int (нули).
var d2 [][]float64 // Только объявление, память не выделяется.
bs := []byte("a slice") // Синтаксис приведения типов.
@@ -113,7 +113,7 @@ func learnTypes() {
delete(m, "three") // Встроенная функция, удаляет элемент из map-а.
// Неиспользуемые переменные в Go являются ошибкой.
- // Нижнее подчеркивание позволяет игнорировать такие переменные.
+ // Нижнее подчёркивание позволяет игнорировать такие переменные.
_, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs
// Вывод считается использованием переменной.
fmt.Println(s, c, a4, s3, d2, m)
@@ -121,16 +121,16 @@ func learnTypes() {
learnFlowControl() // Идем дальше.
}
-// У Go есть полноценный сборщик мусора. В нем есть указатели но нет арифметики
+// У Go есть полноценный сборщик мусора. В нем есть указатели, но нет арифметики
// указателей. Вы можете допустить ошибку с указателем на nil, но не с
// инкрементацией указателя.
func learnMemory() (p, q *int) {
// Именованные возвращаемые значения p и q являются указателями на int.
p = new(int) // Встроенная функция new выделяет память.
- // Выделенный int проинициализирован нулем, p больше не содержит nil.
+ // Выделенный int проинициализирован нулём, p больше не содержит nil.
s := make([]int, 20) // Выделение единого блока памяти под 20 int-ов.
s[3] = 7 // Присвоить значение одному из них.
- r := -2 // Определить еще одну локальную переменную.
+ r := -2 // Определить ещё одну локальную переменную.
return &s[3], &r // Амперсанд(&) обозначает получение адреса переменной.
}
@@ -139,7 +139,7 @@ func expensiveComputation() float64 {
}
func learnFlowControl() {
- // If-ы всегда требуют наличине фигурных скобок, но не круглых.
+ // If-ы всегда требуют наличие фигурных скобок, но не круглых.
if true {
fmt.Println("told ya")
}
@@ -178,7 +178,7 @@ func learnFlowControl() {
}
// Функции являются замыканиями.
xBig := func() bool {
- return x > 10000 // Ссылается на x, объявленый выше switch.
+ return x > 10000 // Ссылается на x, объявленный выше switch.
}
fmt.Println("xBig:", xBig()) // true (т.к. мы присвоили x = e^10).
x = 1.3e3 // Тут х == 1300
@@ -189,7 +189,7 @@ func learnFlowControl() {
love:
learnDefer() // Быстрый обзор важного ключевого слова.
- learnInterfaces() // О! Интерфейсы, идем далее.
+ learnInterfaces() // О! Интерфейсы, идём далее.
}
func learnDefer() (ok bool) {
@@ -214,7 +214,7 @@ type pair struct {
// Объявление метода для типа pair. Теперь pair реализует интерфейс Stringer.
func (p pair) String() string { // p в данном случае называют receiver-ом.
- // Sprintf – еще одна функция из пакета fmt.
+ // Sprintf – ещё одна функция из пакета fmt.
// Обращение к полям p через точку.
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
@@ -234,7 +234,7 @@ func learnInterfaces() {
fmt.Println(p) // Вывод такой же, что и выше. Println вызывает метод String.
fmt.Println(i) // Вывод такой же, что и выше.
- learnVariadicParams("Учиться", "учиться", "и еще раз учиться!")
+ learnVariadicParams("Учиться", "учиться", "и ещё раз учиться!")
}
// Функции могут иметь варьируемое количество параметров.
@@ -263,22 +263,22 @@ func learnErrorHandling() {
// выведет "strconv.ParseInt: parsing "non-int": invalid syntax"
fmt.Println(err)
}
- // Мы еще обратимся к интерфейсам чуть позже, а пока...
+ // Мы ещё обратимся к интерфейсам чуть позже, а пока...
learnConcurrency()
}
-// c – это тип данных channel (канал), объект для конкуррентного взаимодействия.
+// c – это тип данных channel (канал), объект для конкурентного взаимодействия.
func inc(i int, c chan int) {
c <- i + 1 // когда channel слева, <- являтся оператором "отправки".
}
-// Будем использовать функцию inc для конкуррентной инкрементации чисел.
+// Будем использовать функцию inc для конкурентной инкрементации чисел.
func learnConcurrency() {
// Тот же make, что и в случае со slice. Он предназначен для выделения
// памяти и инициализации типов slice, map и channel.
c := make(chan int)
- // Старт трех конкуррентных goroutine. Числа будут инкрементированы
- // конкуррентно и, может быть параллельно, если машина правильно
+ // Старт трех конкурентных goroutine. Числа будут инкрементированы
+ // конкурентно и, может быть параллельно, если машина правильно
// сконфигурирована и позволяет это делать. Все они будут отправлены в один
// и тот же канал.
go inc(0, c) // go начинает новую горутину.
@@ -291,7 +291,7 @@ func learnConcurrency() {
cs := make(chan string) // другой канал, содержит строки.
cc := make(chan chan string) // канал каналов со строками.
go func() { c <- 84 }() // пуск новой горутины для отправки значения
- go func() { cs <- "wordy" }() // еще раз, теперь для cs
+ go func() { cs <- "wordy" }() // ещё раз, теперь для cs
// Select тоже что и switch, но работает с каналами. Он случайно выбирает
// готовый для взаимодействия канал.
select {
@@ -327,7 +327,7 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Основа всех основ в Go это [официальный веб сайт](http://golang.org/).
Там можно пройти туториал, поиграться с интерактивной средой Go и почитать
-объемную документацию.
+объёмную документацию.
Для живого ознакомления рекомендуется почитать исходные коды [стандартной
библиотеки Go](http://golang.org/src/pkg/). Отлично задокументированная, она
diff --git a/ru-ru/haskell-ru.html.markdown b/ru-ru/haskell-ru.html.markdown
new file mode 100644
index 00000000..e15fe6b7
--- /dev/null
+++ b/ru-ru/haskell-ru.html.markdown
@@ -0,0 +1,546 @@
+---
+language: Haskell
+contributors:
+ - ["Adit Bhargava", "http://adit.io"]
+translators:
+ - ["Aleksey Pirogov", "http://astynax.github.io"]
+lang: ru-ru
+---
+
+Haskell разрабатывался, как чистый функциональный язык программирования, применимый на практике. Язык известен благодаря своей системе типов, и "знаменит" благодаря монадам. [Меня][autor] же Haskell заставляет возвращаться к себе снова и снова именно своей элегантностью и [я][autor] получаю истинное удовольствие, программируя на Haskell.
+
+```haskell
+-- Однострочные комментарии начинаются с двух дефисов
+{- Многострочный комментарий
+заключается в пару фигурных скобок с дефисами с внутренней стороны.
+-}
+
+-------------------------------------------------------
+-- 1. Примитивные типы и простейшие операции над ними
+-------------------------------------------------------
+
+-- Числа объявляются просто
+3 -- 3
+
+-- Арифметика тоже выглядит вполне ожидаемо
+1 + 1 -- 2
+8 - 1 -- 7
+10 * 2 -- 20
+35 / 5 -- 7.0
+
+-- Операция деления всегда возвращает действительное число
+35 / 4 -- 8.75
+
+-- Делим нацело так
+35 `div` 4 -- 8
+
+-- Булевы значения - тоже примитивные значения
+True
+False
+
+-- Булева алгебра
+not True -- False
+not False -- True
+1 == 1 -- True
+1 /= 1 -- False
+1 < 10 -- True
+
+-- В примере выше `not`, это функция, принимающая один аргумент.
+-- При вызове функции в Haskell список аргументов
+-- не нужно заключать в скобки - аргументы просто
+-- перечисляются через пробелы сразу после имени функции.
+-- Т.о. типичный вызов выглядит так:
+-- func arg1 arg2 arg3...
+-- Ниже же будет показано, как определять свои функции.
+
+-- Строки и символы
+"Это строка."
+'ы' -- а это символ
+'Нельзя заключать длинные строки в одинарные кавычки.' -- ошибка!
+
+-- Строки можно конкатенировать
+"Привет" ++ ", Мир!" -- "Привет, Мир!"
+
+-- При этом строки - это просто списки символов!
+"Я - строка!" !! 0 -- 'Я'
+
+
+----------------------------------------------------
+-- Списки и Кортежи
+----------------------------------------------------
+
+-- Все элементы списка в Haskell
+-- должны иметь один и тот же тип.
+
+-- Эти два списка - эквивалентны:
+[1, 2, 3, 4, 5]
+[1..5]
+
+-- Haskell позволяет определять даже бесконечные списки!
+[1..] -- список всех натуральных чисел!
+
+-- Бесконечные списки возможно в Haskell потому, что он "ленив".
+-- В Haskell все вычисления производятся тогда и только тогда,
+-- когда их результат потребуется.
+-- Эта стратегия так и называется - "lazy evaluation".
+-- Скажем, если вам нужен тысячный элемент из
+-- списка натуральных чисел (бесконечного) и вы напишете так:
+
+[1..] !! 999 -- 1000
+
+-- То Haskell вычислит элементы этого списка от 1 до 1000...
+-- ... и остановится, ведь последующие элементы пока не нужны.
+-- Это значит, что остальные элементы нашего
+-- "бесконечного" списка не будут вычисляться! По крайней мере,
+-- пока не понадобятся и они.
+
+-- Списки можно объединять
+[1..5] ++ [6..10]
+
+-- И добавлять значения в начало
+0:[1..5] -- [0, 1, 2, 3, 4, 5]
+
+-- А можно обратиться по индексу
+[0..] !! 5 -- 5
+
+-- Вот ещё несколько функций, часто используемых со списками
+head [1..5] -- 1
+tail [1..5] -- [2, 3, 4, 5]
+init [1..5] -- [1, 2, 3, 4]
+last [1..5] -- 5
+
+-- list comprehensions - "формулы" для описания списков
+[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10]
+
+-- можно указать условие попадания элементов в список
+[x*2 | x <- [1..5], x*2 > 4] -- [6, 8, 10]
+
+-- Списки могут даже состоять из других списков
+[[1,2,3],[4,5,6]] !! 1 !! 2 -- 6 (вторая строка, третий столбец)
+
+-- Кортежи позволяют своим элементам иметь различные типы,
+-- но при этом кортежи имеют фиксированную длину.
+-- Кортеж:
+("haskell", 1)
+
+-- Часто кортежи из двух элементов называются "парами".
+-- Элементы пары можно получать так:
+fst ("haskell", 1) -- "haskell"
+snd ("haskell", 1) -- 1
+
+----------------------------------------------------
+-- 3. Функции
+----------------------------------------------------
+-- Простая функция, принимающая два аргумента
+add a b = a + b
+
+-- Внимание!
+-- Если вы используете ghci (интерактивный интерпретатор Haskell),
+-- вам нужно использовать ключевое слово `let`, примерно так:
+-- let add a b = a + b
+
+-- Вызовем нашу функцию
+add 1 2 -- 3
+
+-- Функцию можно поместить между первым и вторым аргументами,
+-- если заключить её имя в обратные кавычки
+1 `add` 2 -- 3
+
+{- Вы можете также определять функции, имя которых
+вообще не содержит букв! Таки функции и называются "операторами",
+и, да, вы можете определять свои операторы!
+Скажем, оператор целочисленного деления можно определить так -}
+(//) a b = a `div` b
+35 // 4 -- 8
+{- Здесь оператор заключен в скобки - как говорят,
+поставлен в префиксную позицию.
+В префиксной позиции оператор можно не только определять,
+но и вызывать -}
+(+) 1 2 -- 3
+
+-- Охранные выражения (guards) порой удобны,
+-- если наша функция ветвится
+fib x
+ | x < 2 = x
+ | otherwise = fib (x - 1) + fib (x - 2)
+
+{- Сопоставление с образцом (pattern matching)
+чем-то напоминает охранные выражения.
+Здесь мы видим три определения функции fib.
+При вызове функции по имени Haskell использует
+первое определение, к образцу которого
+"подойдет" набор аргументов -}
+fib 1 = 1
+fib 2 = 2
+fib x = fib (x - 1) + fib (x - 2)
+
+-- Pattern matching для кортежей выглядит так
+foo (x, y) = (x + 1, y + 2)
+
+{- Pattern matching для списков устроен чуть сложнее.
+Пусть `x` - первый элемент списка, а `xs` - остальные элементы.
+Тогда операции `head` и `tail` могут быть определены так -}
+myHead (x:xs) = x
+myTail (x:xs) = xs
+
+-- Функцию отображения мы можем написать так
+myMap func [] = []
+myMap func (x:xs) = func x:(myMap func xs)
+
+-- При сопоставлении происходит привязка
+-- элементов значения с именами в образце
+fstPlusThird (a : _ : b : _) = a + b
+fstPlusThird [1,2,3,4,5] -- 4
+-- Значения, для которых вместо имени указано `_`,
+-- игнорируются. Это удобно, когда важен сам факт
+-- совпадения образца
+oneElem [_] = True
+oneElem _ = False
+
+startsWith x (y:_) = x == y
+startsWith _ _ = False
+
+startsWith 'H' "Hello!" -- True
+startsWith 'H' "hello!" -- False
+
+{- Обратите внимание на тот факт,
+что первый аргумент нашей функции `myMap` - тоже функция!
+Функции, подобно `myMap`, принимающие другие функции
+в качестве параметров, или, скажем, возвращающие функции
+в качестве результата, называются
+Функциями Высших Порядков (ФВП, High Order Functions, HOF)
+-}
+
+-- Вместе с ФВП часто используются анонимные функции
+myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7]
+-- Такие функции описываются в виде
+-- \arg1 arg1 .. -> expression
+
+-- Популярные в других языках ФВП присутствуют и в Haskell
+map (\x -> x * 10) [1..5] -- [10, 20, 30, 40, 50]
+filter (\x -> x > 2) [1..5] -- [3, 4, 5]
+
+{- Функция свертки
+(она же `reduce` или `inject` в других языках)
+в Haskell представлены функциями `foldr` и `foldl`.
+Суть свертки можно представить так:
+
+foldl f x0 [x1,x2,x3] -> (f (f (f x0 x1) x2) x3)
+foldr f x0 [x1,x2,x3] -> (f x1 (f x2 (f x3 x0)))
+
+Здесь x0 - начальное значения так называемого "аккумулятора"
+-}
+-- Эти два вызова дают одинаковый результат
+foldr (\x acc -> acc + x) 0 [1..5] -- 15
+foldl (\acc x -> acc + x) 0 [1..5] -- 15
+-- Тут можно даже заменить анонимную функцию на оператор
+foldr (+) 0 [1..5] -- 15
+foldl (+) 0 [1..5] -- 15
+
+-- Зато здесь разница видна
+foldr (\x acc -> (x + 10) : acc) [] [1..3] -- [11, 12, 13]
+foldl (\acc x -> (x + 10) : acc) [] [1..3] -- [13, 12, 11]
+
+{- Часто в качестве начального значения
+удобно брать крайнее значение списка (крайнее слева или справа).
+Для этого есть пара функций - `foldr1` и `foldl1` -}
+foldr1 (+) [1..5] -- 15
+foldl1 (+) [1..5] -- 15
+
+----------------------------------------------------
+-- 4. Больше о функциях
+----------------------------------------------------
+
+{- Каррирование (currying)
+Если в Haskell при вызове функции передать не все аргументы,
+Функция становится "каррированой" - результатом вызова станет
+новая функция, которая при вызове и примет оставшиеся аргументы -}
+
+add a b = a + b
+foo = add 10 -- теперь foo будет принимать число
+ -- и добавлять к нему 10
+foo 5 -- 15
+
+-- Для операторов можно "опустить" любой из двух аргументов
+-- Используя этот факт можно определить
+-- функцию `foo` из кода выше несколько иначе
+foo = (+10)
+foo 5 -- 15
+
+-- Поупражняемся
+map (10-) [1..3] -- [9, 8, 7]
+filter (<5) [1..10] -- [1, 2, 3, 4]
+
+{- Композиция функций
+Функция (.) соединяет пару функций в цепочку.
+К примеру, можно соединить функцию, добавляющую 10,
+с функцией, умножающей на 5 -}
+foo = (*5) . (+10)
+
+-- (5 + 10) * 5 = 75
+foo 5 -- 75
+
+{- Управление приоритетом вычисления
+В Haskell есть функция `$`, которая применяет
+свой первый аргумент ко второму с наименьшим приоритетом
+(обычное применение функций имеет наивысший приоритет)
+Эта функция часто позволяет избежать использования
+"лишних" скобок -}
+head (tail (tail "abcd")) -- 'c'
+head $ tail $ tail "abcd" -- 'c'
+-- того же эффекта иногда можно достичь использованием композиции
+(head . tail . tail) "abcd" -- 'c'
+head . tail . tail $ "abcd" -- 'c'
+{- Тут стоит сразу запомнить, что композиция функций
+возвращает именно новую функцию, как в последнем примере.
+Т.е. можно делать так -}
+third = head . tail . tail
+-- но не так
+third = head $ tail $ tail -- (head (tail (tail))) - ошибка!
+
+----------------------------------------------------
+-- 5. Сигнатуры типов
+----------------------------------------------------
+
+{- Haskell обладает очень сильной системой типов.
+И типизация в Haskell - строгая. Каждое выражение имеет тип,
+который может быть описан сигнатурой.
+Сигнатура записывается в форме
+expression :: type signature
+-}
+
+-- Типы примитивов
+5 :: Integer
+"hello" :: String
+True :: Bool
+
+{- Функции тоже имеют тип
+`not` принимает булево значение и возвращает булев результат
+not :: Bool -> Bool
+
+Вот функция двух аргументов
+add :: Integer -> Integer -> Integer
+
+Тут то мы и видим предпосылки к каррированию: тип
+на самом деле выглядит так (скобки просто обычно опускаются)
+add :: (Integer -> Integer) -> Integer
+т.е. функция принимает аргумент,
+и возвращает функцию от второго аргумента! -}
+
+-- Считается хорошим тоном указывать сигнатуру определений,
+-- которые доступны другим разработчикам (публичны). Пример:
+double :: Integer -> Integer
+double x = x * 2
+
+----------------------------------------------------
+-- 6. Управление потоком исполнения
+----------------------------------------------------
+
+-- Выражение `if`
+haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome"
+
+-- Выражение `if` можно записать и в несколько строк.
+-- Соблюдайте отступы!
+haskell = if 1 == 1
+ then "awesome"
+ else "awful"
+
+-- Так как `if` - выражение, ветка `else` обязательна!
+-- И более того, результаты выражений в ветках `then` и `else`
+-- должны иметь одинаковый тип!
+
+-- `case`-выражение выглядит так
+case args of -- парсим аргументы командной строки
+ "help" -> printHelp
+ "start" -> startProgram
+ _ -> putStrLn "bad args"
+
+-- При вычислении результата `case`-выражения производится
+-- сопоставление с образцом:
+fib x = case x of
+ 1 -> 1
+ 2 -> 1
+ _ -> fib (x - 1) + fib (x - 2)
+
+-- В Haskell нет циклов - вместо них используются рекурсия,
+-- отображение, фильтрация и свертка (map/filter/fold)
+map (*2) [1..5] -- [2, 4, 6, 8, 10]
+
+for array func = map func array
+for [0..3] $ \i -> show i -- ["0", "1", "2", "3"]
+for [0..3] show -- ["0", "1", "2", "3"]
+
+----------------------------------------------------
+-- 7. Пользовательские типы данных
+----------------------------------------------------
+
+-- Создадим свой Haskell-тип данных
+
+data Color = Red | Blue | Green
+
+-- Попробуем использовать
+
+say :: Color -> String
+say Red = "You are Red!"
+say Blue = "You are Blue!"
+say Green = "You are Green!"
+
+-- Типы могут иметь параметры (параметры типов)
+
+data Maybe a = Nothing | Just a
+
+-- Все эти выражения имеют тип `Maybe`
+Just "hello" -- :: `Maybe String`
+Just 1 -- :: `Maybe Int`
+Nothing -- :: `Maybe a` для любого `a`
+
+-- Типы могут быть достаточно сложными
+data Figure = Rectangle (Int, Int) Int Int
+ | Square (Int, Int) Int
+ | Point (Int, Int)
+
+area :: Figure -> Int
+area (Point _) = 0
+area (Square _ s) = s * s
+area (Rectangle _ w h) = w * h
+
+----------------------------------------------------
+-- 8. Ввод-вывод в Haskell
+----------------------------------------------------
+
+-- Полноценно объяснить тему ввода-вывода невозможно
+-- без объяснения монад, но для использования в простых случаях
+-- вводного описания будет достаточно.
+
+-- Когда программа на Haskell выполняется,
+-- вызывается функция с именем `main`.
+-- Эта функция должна вернуть значение типа `IO ()`
+-- Например
+
+main :: IO ()
+main = putStrLn $ "Hello, sky! " ++ (say Blue)
+-- `putStrLn` имеет тип `String -> IO ()`
+
+-- Проще всего реализовать программу с вводом-выводом (IO),
+-- если вы реализуете функцию с типом `String -> String`.
+-- Далее ФВП
+-- interact :: (String -> String) -> IO ()
+-- сделает всё за нас!
+
+countLines :: String -> String
+countLines = show . length . lines
+-- здесь `lines` разделяет строку на список строк
+-- по символу перевода строки
+
+main' :: IO ()
+main' = interact countLines
+
+{- Вы можете думать о типе `IO ()`,
+как о некотором представлении последовательности
+действий, которые должен совершить компьютер.
+Такое представление напоминает программу
+на императивном языке программирования. Для описания
+такой последовательности используется `do`-нотация -}
+
+sayHello :: IO ()
+sayHello = do
+ putStrLn "What is your name?"
+ name <- getLine -- запрашиваем строку и связываем с "name"
+ putStrLn $ "Hello, " ++ name
+
+-- Упражнение:
+-- напишите свою реализацию функции `interact`,
+-- которая запрашивает и обрабатывает только одну строку
+
+{- Код функции `sayHello` не будет исполняться
+при её определении. Единственное место, где IO-действия
+могут быть произведены - функция `main`!
+Чтобы эта программа выполнила действия в функции `sayHello`,
+закомментируйте предыдущее определение функции `main`
+и добавьте новое определение:
+
+main = sayHello -}
+
+{- Давайте подробнее рассмотрим, как работает функция `getLine`
+Её тип:
+ getLine :: IO String
+Вы можете думать, что значение типа `IO a` представляет
+собой компьютерную программу, в результате выполнения которой
+генерируется значение типа `a`, в дополнение
+к остальным эффектам, производимым при выполнении - таким как
+печать текста на экран. Это значение типа `a` мы можем
+сохранить с помощью оператора `<-`. Мы даже можем реализовать
+свое действие, возвращающее значение: -}
+
+action :: IO String
+action = do
+ putStrLn "This is a line. Duh"
+ input1 <- getLine
+ input2 <- getLine
+ -- Тип блока `do` будет соответствовать типу последнего
+ -- выполненного в блоке выражения.
+ -- Заметим, что `return` - не ключевое слово, а функция
+ -- типа `a -> IO a`
+ return (input1 ++ "\n" ++ input2) -- return :: String -> IO String
+
+-- Теперь это действие можно использовать вместо `getLine`:
+
+main'' = do
+ putStrLn "I will echo two lines!"
+ result <- action
+ putStrLn result
+ putStrLn "This was all, folks!"
+
+{- Тип `IO` - пример "монады". Языку Haskell нужны монады,
+чтобы оставаться преимущественно чистым функциональным языком.
+Любые функции, взаимодействующие с внешним миром
+(производящие ввод-вывод) имеют `IO` в своих сигнатурах.
+Это позволяет судить о функции как о "чистой" - такая не будет
+производить ввод-вывод. В ином случая функция - не "чистая".
+
+Такой подход позволяет очень просто разрабатывать многопоточные
+программы - чистые функции, запущенные параллельно
+не будут конфликтовать между собой в борьбе за ресурсы. -}
+
+----------------------------------------------------
+-- 9. Haskell REPL
+----------------------------------------------------
+
+{- Интерактивная консоль Haskell запускается командой `ghci`.
+Теперь можно вводить строки кода на Haskell.
+Связывание значений с именами производится
+с помощью выражения `let`: -}
+
+let foo = 5
+
+-- Тип значения или выражения можно узнать
+-- с помощью команды `:t`:
+
+>:t foo
+foo :: Integer
+
+-- Также можно выполнять действия с типом `IO ()`
+
+> sayHello
+What is your name?
+Friend!
+Hello, Friend!
+
+```
+
+Многое о Haskell, например классы типов и монады невозможно уместить в столь короткую статью. Огромное количество очень интересных идей лежит в основе языка, и именно благодаря этому фундаменту на языке так приятно писать код. Позволю себе привести ещё один маленький пример кода на Haskell - реализацию быстрой сортировки:
+
+```haskell
+qsort [] = []
+qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
+ where lesser = filter (< p) xs
+ greater = filter (>= p) xs
+```
+
+Haskell прост в установке, забирайте [здесь](http://www.haskell.org/platform/) и пробуйте! Это же так интересно!.
+
+Более глубокое погрузиться в язык позволят прекрасные книги
+[Learn you a Haskell](http://learnyouahaskell.com/) и
+[Real World Haskell](http://book.realworldhaskell.org/).
+
+[autor]: http://adit.io имеется в виду автор оригинального текста Adit Bhargava *(примечание переводчика)*
diff --git a/ru-ru/julia-ru.html.markdown b/ru-ru/julia-ru.html.markdown
index cd55e116..29392604 100644
--- a/ru-ru/julia-ru.html.markdown
+++ b/ru-ru/julia-ru.html.markdown
@@ -1,5 +1,5 @@
---
-language: julia
+language: Julia
contributors:
- ["Leah Hanson", "http://leahhanson.us"]
translators:
diff --git a/ru-ru/markdown-ru.html.markdown b/ru-ru/markdown-ru.html.markdown
new file mode 100644
index 00000000..eb8e4881
--- /dev/null
+++ b/ru-ru/markdown-ru.html.markdown
@@ -0,0 +1,279 @@
+---
+language: markdown
+contributors:
+ - ["Dan Turkel", "http://danturkel.com/"]
+ - ["Pirogov Alexey", "http://twitter.com/alex_pir"]
+filename: markdown-ru.md
+lang: ru-ru
+---
+
+Язык разметки Markdown создан Джоном Грубером (англ. John Gruber)
+и Аароном Шварцем (англ. Aaron H. Swartz) в 2004 году.
+Авторы задавались целью создать максимально удобочитаемый
+и удобный в публикации облегчённый язык разметки,
+пригодный для последующего преобразования в HTML
+(а также и в другие форматы).
+
+ ```markdown
+<!-- Markdown является надмножеством HTML, поэтому любой HTML-файл является
+валидным документом Markdown, что позволяет использовать напрямую
+любые элементы HTML-разметки, такие, например, как этот комментарий.
+ Встроенные в документ HTML-элементы не затрагиваются парсером Markdown
+и попадают в итоговый HTML без изменений. Однако, следует понимать,
+что эта же особенность не позволяет использовать разметку Markdown внутри
+HTML-элементов -->
+
+<!-- Ещё одна особенность формата Markdown состоит в том, что поддерживаемые
+возможности разметки зависят от конкретной реализации парсера. В данном
+руководстве возможности, поддерживаемые лишь определёнными парсерами,
+сопровождаются соответствующими примечаниями. -->
+
+<!-- Заголовки -->
+
+<!-- HTML-элементы от <h1> до <h6> размечаются очень просто:
+текст, который должен стать заголовком, предваряется
+соответствующим количеством символов "#": -->
+# Это заголовок h1
+## Это заголовок h2
+### Это заголовок h3
+#### Это заголовок h4
+##### Это заголовок h5
+###### Это заголовок h6
+
+<!-- Markdown позволяет размечать заголовки <h1> и <h2> ещё одним способом: -->
+Это заголовок h1
+================
+
+А это заголовок h2
+------------------
+
+<!-- Простейшая стилизация текста -->
+
+<!-- Текст легко сделать полужирным и/или курсивным: -->
+
+*Этот текст будет выведен курсивом.*
+_Так же, как этот._
+
+**А этот текст будет полужирным.**
+__И этот тоже.__
+
+***Полужирный курсив.***
+**_И тут!_**
+*__И даже здесь!__*
+
+<!-- В Github Flavored Markdown (версии Markdown, использующейся в Github,
+для рендеринга Markdown-документов) текст можно сделать зачёркнутым: -->
+
+~~Зачёркнутый текст.~~
+
+<!-- Абзацами являются любые строки, следующие друг за другом.
+Разделяются же абзацы одной или несколькими пустыми строками: -->
+
+Это абзац. Всё предельно просто.
+
+А тут уже параграф №2.
+Эта строка всё ещё относится к параграфу №2!
+
+
+О, а вот это уже параграф №3!
+
+<!-- Для вставки принудительных переносов можно использовать HTML-тэг <br/>: -->
+
+Принудительный <br/> перенос!
+
+<!-- Цитаты размечаются с помощью символа ">": -->
+
+> Это цитата. В цитатах можно
+> принудительно переносить строки, вставляя ">" в начало каждой следующей строки. А можно просто оставлять достаточно длинными, и такие длинные строки будут перенесены автоматически.
+> Разницы между этими двумя подходами к переносу строк нет, коль скоро
+> каждая строка начинается с символа ">"
+
+> А ещё цитаты могут быть многоуровневыми:
+>> как здесь
+>>> и здесь :)
+> Неплохо?
+
+<!-- Списки -->
+<!-- Маркированные списки размечаются вставкой в начало каждого элемента
+одного из символов "*", "+" или "-":
+(символ должен быть одним и тем же для всех элементов) -->
+
+* Список,
+* Размеченный
+* Звёздочками
+
+либо
+
++ Список,
++ Размеченный
++ Плюсами
+
+либо
+
+- Список,
+- Размеченный
+- Дефисами
+
+<!-- В нумерованных списках каждая строка начинается
+с числа и точки вслед за ним: -->
+
+1. Первый элемент
+2. Второй элемент
+3. Третий элемент
+
+<!-- Заметьте, нумеровать элементы корректно необязательно. Достаточно указать
+любое число в начале каждого элемента и рендер пронумерует элементы сам!
+Правда, злоупотреблять этим не стоит :) -->
+
+1. Первый элемент
+1. Второй элемент
+1. Третий элемент
+<!-- (Этот список будет отрендерен так же, как и предыдущий!) -->
+
+<!-- Списки могут быть вложенными: -->
+
+1. Введение
+2. Начало работы
+3. Примеры использования
+ * Простые
+ * Сложные
+4. Заключение
+
+<!-- Блоки с исходным кодом -->
+<!-- Фрагменты исходного кода выделяются очень просто - каждая строка блока должна иметь отступ в четыре пробела либо в один символ табуляции -->
+
+ Это код,
+ причём - многострочный
+
+<!-- Дополнительные отступы в коде следует делать с помощью четырёх пробелов: -->
+
+ my_array.each do |item|
+ puts item
+ end
+
+<!-- Иногда бывает нужно вставить фрагмент кода прямо в строку текста,
+не выделяя код в блок. Для этого фрагменты кода нужно обрамлять
+символами "`": -->
+
+Например, можно выделить имя функции `go_to()` прямо посреди текста.
+
+<!-- Github Flavored Markdown позволяет указать для блока кода синтаксис оного.
+В этом случае синтаксис внутри блока будет подсвечен. Пример: -->
+
+\`\`\`ruby <!-- Только нужно будет убрать символы "\", оставив лишь "```ruby" -->
+def foobar
+ puts "Hello world!"
+end
+\`\`\` <!-- И здесь тоже backslashes нужно убрать, т.е. оставить "```" -->
+
+<-- Обратите внимание: фрагмент, указанный выше, не предваряется отступами,
+поскольку Github сам в состоянии определить границы блока - по строкам "```" -->
+
+<!-- Горизонтальный разделитель (<hr />) -->
+<!-- Разделители добавляются вставкой строки из трёх и более
+(одинаковых) символов "*" или "-": -->
+
+***
+---
+- - - <!-- между символами допустимы пробелы -->
+****************
+
+<!-- Ссылки -->
+<!-- Одной из сильных сторон Markdown можно смело считать то,
+как просто размечаются гиперссылки. Для создания ссылки укажите
+текст ссылки, заключив его в квадратные скобки,
+и сразу после - url, заключенный в "круглые" -->
+
+[Ссылка!](http://test.com/)
+
+<!-- Также для ссылки можно указать всплывающую подсказку: -->
+
+[Ссылка!](http://test.com/ "Ссылка на Test.com")
+
+<!-- В url можно использовать относительные пути: -->
+
+[Перейти к музыке](/music/).
+
+<!-- Markdown позволяет размечать ссылку в виде сноски: -->
+
+[Здесь][link1] высможете узнать больше!
+А можно кликнуть [сюда][foobar], если очень хочется.
+
+<!-- где-нибудь внизу -->
+[link1]: http://test.com/ "Круто!"
+[foobar]: http://foobar.biz/ "Тоже хорошо!"
+
+<!-- Примечания:
+- Подсказка может быть заключена в одинарные кавычки вместо двойных,
+ а также в круглые скобки.
+- Сноска может находиться в любом месте документа и может иметь
+идентификатор (далее ID) произвольной длины,
+лишь бы это ID был уникальным. -->
+
+<!-- Также при разметке ссылок-сносок можно опустить ID,
+если текст ссылки уникален в пределах документа: -->
+
+Ссылка на [Google][].
+
+[google]: http://google.com/
+
+<!-- Правда, эта возможность не очень распространена. -->
+
+<!-- Изображения -->
+<!-- Разметка изображений очень похожа на разметку ссылок.
+Нужно всего лишь добавить "!" перед ссылкой! -->
+
+![Альтернативный текст для изображения](http://imgur.com/myimage.jpg "Подсказка")
+
+<!-- Изображения тоже могут быть оформлены, как сноски: -->
+
+![Альтернативный текст][myimage]
+
+![То же изображение ещё раз][myimage]
+
+[myimage]: relative/urls/cool/image.jpg "подсказка"
+
+<!-- Ещё немного ссылок: -->
+<!-- Автоссылки -->
+
+Ссылка вида <http://testwebsite.com/> эквивалентна
+[http://testwebsite.com/](http://testwebsite.com/)
+
+<!-- Автоссылки для адресов электронной почты -->
+
+<foo@bar.com>
+
+<!-- Экранирование символов -->
+
+<!-- Может потребоваться вставить спецсимвол в текст "как есть",
+т.е. защитить его от обработки парсером.
+Такой символ должен быть "экранирован" с помощью обратной косой черты
+(символа "\"): -->
+
+\*текст, заключённый в звёздочки!\*
+
+<!-- Таблицы -->
+<!-- Таблицы официально поддерживаются только в Github Flavored Markdown,
+да и синтаксис имеют не слишком удобный.
+Но если очень нужно, размечайте таблицы так: -->
+
+| Столбец 1 | Столбец 2 | Столбец 3 |
+| :----------- | :----------: | -----------: |
+| Выравнивание | Выравнивание | Выравнивание |
+| влево | по центру | вправо |
+
+<!-- Или более компактно -->
+
+Колонка 1|Колонка 2|Колонка 3
+:--|:-:|--:
+Выглядит|это|страшновато...
+
+<!-- Ну вот и всё! -->
+
+```
+
+За более подробной информацией обращайтесь к [статье](http://daringfireball.net/projects/markdown/syntax) Джона Грубера о синтаксисе Markdown.
+
+Также часто бывает полезной отличная ["шпаргалка"](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) по Markdown от Adam Pritchard.
+
+Если вдруг встретите ошибки в переводе или же захотите его дополнить, делайте pull requests - авторы всегда рады обратной связи!
diff --git a/ru-ru/objective-c-ru.html.markdown b/ru-ru/objective-c-ru.html.markdown
index 72e3b9e0..3246de82 100644
--- a/ru-ru/objective-c-ru.html.markdown
+++ b/ru-ru/objective-c-ru.html.markdown
@@ -13,7 +13,7 @@ Objective-C — компилируемый объектно-ориентиров
построенный на основе языка Си и парадигм Smalltalk.
В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения.
-```cpp
+```objective_c
// Однострочный комментарий
/*
diff --git a/ru-ru/php-ru.html.markdown b/ru-ru/php-ru.html.markdown
index edcac4dd..53b2f916 100644
--- a/ru-ru/php-ru.html.markdown
+++ b/ru-ru/php-ru.html.markdown
@@ -1,5 +1,5 @@
---
-language: php
+language: PHP
contributors:
- ["Malcolm Fell", "http://emarref.net/"]
- ["Trismegiste", "https://github.com/Trismegiste"]
diff --git a/ru-ru/python-ru.html.markdown b/ru-ru/python-ru.html.markdown
index 204eb357..d59d3e21 100644
--- a/ru-ru/python-ru.html.markdown
+++ b/ru-ru/python-ru.html.markdown
@@ -5,25 +5,29 @@ contributors:
- ["Louie Dinh", "http://ldinh.ca"]
translators:
- ["Yury Timofeev", "http://twitter.com/gagar1n"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
filename: learnpython-ru.py
---
-Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из самых популярных
-языков. Я люблю его за его понятный и доходчивый синтаксис - это почти что исполняемый псевдокод.
+Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из
+самых популярных языков. Я люблю его за понятный и доходчивый синтаксис — это
+почти что исполняемый псевдокод.
-С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh) или louiedinh [at] [google's email service]
+С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)
+или louiedinh [at] [почтовый сервис Google]
-Замечание: Эта статья относится к Python 2.7, но должно работать и в Python 2.x. Скоро будет версия и для Python 3!
+Замечание: Эта статья относится к Python 2.7, но должно работать и в Python 2.x.
+Скоро будет версия и для Python 3!
```python
-# Однострочные комментарии начинаются с hash-символа.
+# Однострочные комментарии начинаются с символа решётки.
""" Многострочный текст может быть
записан, используя 3 знака " и обычно используется
в качестве комментария
"""
####################################################
-## 1. Примитивные типы данных и операторов
+## 1. Примитивные типы данных и операторы
####################################################
# У вас есть числа
@@ -36,17 +40,31 @@ filename: learnpython-ru.py
35 / 5 #=> 7
# А вот деление немного сложнее. В этом случае происходит деление
-# целых чисел и результат автоматически округляется в меньшую сторону.
+# целых чисел, и результат автоматически округляется в меньшую сторону.
5 / 2 #=> 2
-# Чтобы научиться делить, сначала нужно немного узнать о дробных числах.
-2.0 # Это дробное число
+# Чтобы научиться делить, сначала нужно немного узнать о числах
+# с плавающей запятой.
+2.0 # Это число с плавающей запятой
11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше
+# Результат целочисленного деления округляется в меньшую сторону
+# как для положительных, так и для отрицательных чисел.
+5 // 3 # => 1
+5.0 // 3.0 # => 1.0 # работает и для чисел с плавающей запятой
+-5 // 3 # => -2
+-5.0 // 3.0 # => -2.0
+
+# Остаток от деления
+7 % 3 # => 1
+
+# Возведение в степень
+2 ** 4 # => 16
+
# Приоритет операций указывается скобками
(1 + 3) * 2 #=> 8
-# Логические значения являются примитивами
+# Логические (булевы) значения являются примитивами
True
False
@@ -54,15 +72,15 @@ False
not True #=> False
not False #=> True
-# Равенство это ==
+# Равенство — это ==
1 == 1 #=> True
2 == 1 #=> False
-# Неравенство это !=
+# Неравенство — это !=
1 != 1 #=> False
2 != 1 #=> True
-# Еще немного сравнений
+# Ещё немного сравнений
1 < 10 #=> True
1 > 10 #=> False
2 <= 2 #=> True
@@ -85,9 +103,10 @@ not False #=> True
# Символ % используется для форматирования строк, например:
"%s могут быть %s" % ("строки", "интерполированы")
-# Новый метод форматирования строк - использование метода format.
+# Новый способ форматирования строк — использование метода format.
# Это предпочитаемый способ.
"{0} могут быть {1}".format("строки", "форматированы")
+
# Если вы не хотите считать, можете использовать ключевые слова.
"{name} хочет есть {food}".format(name="Боб", food="лазанью")
@@ -95,7 +114,7 @@ not False #=> True
None #=> None
# Не используйте оператор равенства '=='' для сравнения
-# объектов с None. Используйте для этого 'is'
+# объектов с None. Используйте для этого «is»
"etc" is None #=> False
None is None #=> True
@@ -113,17 +132,18 @@ None is None #=> True
## 2. Переменные и коллекции
####################################################
-# Печатать довольно просто
-print "Я Python. Приятно познакомиться!"
-
+# У Python есть функция Print, доступная в версиях 2.7 и 3,
+print("Я Python. Приятно познакомиться!")
+# ...и старый оператор print, доступный в версиях 2.x, но удалённый в версии 3.
+print "И я тоже Python!"
# Необязательно объявлять переменные перед их инициализацией.
-some_var = 5 # По соглашению используется нижний_регистр_с_подчеркиваниями
+some_var = 5 # По соглашению используется нижний_регистр_с_подчёркиваниями
some_var #=> 5
-# При попытке доступа к неинициализированной переменной,
+# При попытке доступа к неинициализированной переменной
# выбрасывается исключение.
-# См. раздел "Поток управления" для информации об исключениях.
+# См. раздел «Поток управления» для информации об исключениях.
some_other_var # Выбрасывает ошибку именования
# if может быть использован как выражение
@@ -149,24 +169,30 @@ li[0] #=> 1
# Обратимся к последнему элементу
li[-1] #=> 3
-# Попытка выйти за границы массива приведет к IndexError
-li[4] # Выдает IndexError
+# Попытка выйти за границы массива приведёт к ошибке индекса
+li[4] # Выдаёт IndexError
# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax)
-# (Для тех, кто любит математику, это называется замкнуто/открытый интервал.)
+# (Для тех, кто любит математику, это называется замкнуто-открытый интервал).
li[1:3] #=> [2, 4]
# Опускаем начало
li[2:] #=> [4, 3]
# Опускаем конец
li[:3] #=> [1, 2, 4]
+# Выбираем каждый второй элемент
+li[::2] # =>[1, 4]
+# Переворачиваем список
+li[::-1] # => [3, 4, 2, 1]
+# Используйте сочетания всего вышеназванного для выделения более сложных кусков
+# li[начало:конец:шаг]
# Удаляем произвольные элементы из списка оператором del
del li[2] # [1, 2, 3]
# Вы можете складывать списки
-li + other_li #=> [1, 2, 3, 4, 5, 6] - Замечание: li и other_li остаются нетронутыми
+li + other_li #=> [1, 2, 3, 4, 5, 6] — Замечание: li и other_li не изменяются
-# Конкатенировать списки можно методом extend
+# Объединять списки можно методом extend
li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6]
# Проверить элемент на вхождение в список можно оператором in
@@ -176,12 +202,12 @@ li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6]
len(li) #=> 6
-# Кортежи - это такие списки, только неизменяемые
+# Кортежи — это такие списки, только неизменяемые
tup = (1, 2, 3)
tup[0] #=> 1
-tup[0] = 3 # Выдает TypeError
+tup[0] = 3 # Выдаёт TypeError
-# Все то же самое можно делать и с кортежами
+# Всё то же самое можно делать и с кортежами
len(tup) #=> 3
tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
tup[:2] #=> (1, 2)
@@ -203,33 +229,33 @@ filled_dict = {"one": 1, "two": 2, "three": 3}
# Значения ищутся по ключу с помощью оператора []
filled_dict["one"] #=> 1
-# Можно получить все ключи в виде списка
+# Можно получить все ключи в виде списка с помощью метода keys
filled_dict.keys() #=> ["three", "two", "one"]
-# Замечание - сохранение порядка ключей в словаре не гарантируется
+# Замечание: сохранение порядка ключей в словаре не гарантируется
# Ваши результаты могут не совпадать с этими.
-# Можно получить и все значения в виде списка
+# Можно получить и все значения в виде списка, используйте метод values
filled_dict.values() #=> [3, 2, 1]
-# То же самое замечание насчет порядка ключей справедливо и здесь
+# То же самое замечание насчёт порядка ключей справедливо и здесь
# При помощи оператора in можно проверять ключи на вхождение в словарь
"one" in filled_dict #=> True
1 in filled_dict #=> False
-# Попытка получить значение по несуществующему ключу выбросит KeyError
+# Попытка получить значение по несуществующему ключу выбросит ошибку ключа
filled_dict["four"] # KeyError
# Чтобы избежать этого, используйте метод get
filled_dict.get("one") #=> 1
filled_dict.get("four") #=> None
-# Метод get также принимает аргумент default, значение которого будет
+# Метод get также принимает аргумент по умолчанию, значение которого будет
# возвращено при отсутствии указанного ключа
filled_dict.get("one", 4) #=> 1
filled_dict.get("four", 4) #=> 4
-# Метод setdefault - это безопасный способ добавить новую пару ключ-значение в словарь
+# Метод setdefault вставляет пару ключ-значение, только если такого ключа нет
filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5
-filled_dict.setdefault("five", 6) #filled_dict["five"] по прежнему возвращает 5
+filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5
# Множества содержат... ну, в общем, множества
@@ -237,8 +263,8 @@ empty_set = set()
# Инициализация множества набором значений
some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4])
-# Начиная с Python 2.7, вы можете использовать {} чтобы обьявить множество
-filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
+# Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество
+filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4}
# Добавление новых элементов в множество
filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5}
@@ -262,33 +288,33 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
## 3. Поток управления
####################################################
-# Для начала заведем переменную
+# Для начала заведём переменную
some_var = 5
# Так выглядит выражение if. Отступы в python очень важны!
-# результат: "some_var меньше, чем 10"
+# результат: «some_var меньше, чем 10»
if some_var > 10:
- print "some_var намного больше, чем 10."
+ print("some_var намного больше, чем 10.")
elif some_var < 10: # Выражение elif необязательно.
- print "some_var меньше, чем 10."
+ print("some_var меньше, чем 10.")
else: # Это тоже необязательно.
- print "some_var равно 10."
+ print("some_var равно 10.")
"""
Циклы For проходят по спискам
Результат:
- собака это млекопитающее
- кошка это млекопитающее
- мышь это млекопитающее
+ собака — это млекопитающее
+ кошка — это млекопитающее
+ мышь — это млекопитающее
"""
for animal in ["собака", "кошка", "мышь"]:
# Можете использовать оператор % для интерполяции форматированных строк
- print "%s это млекопитающее" % animal
+ print("%s — это млекопитающее" % animal)
"""
-`range(number)` возвращает список чисел
+«range(число)» возвращает список чисел
от нуля до заданного числа
Результат:
0
@@ -297,7 +323,7 @@ for animal in ["собака", "кошка", "мышь"]:
3
"""
for i in range(4):
- print i
+ print(i)
"""
Циклы while продолжаются до тех пор, пока указанное условие не станет ложным.
@@ -309,19 +335,24 @@ for i in range(4):
"""
x = 0
while x < 4:
- print x
- x += 1 # То же самое, что x = x + 1
+ print(x)
+ x += 1 # Краткая запись для x = x + 1
-# Обрабывайте исключения блоками try/except
+# Обрабатывайте исключения блоками try/except
# Работает в Python 2.6 и выше:
try:
- # Для выбора ошибки используется raise
- raise IndexError("Это IndexError")
+ # Чтобы выбросить ошибку, используется raise
+ raise IndexError("Это ошибка индекса")
except IndexError as e:
# pass это просто отсутствие оператора. Обычно здесь происходит
- # восстановление от ошибки.
+ # восстановление после ошибки.
pass
+except (TypeError, NameError):
+ pass # Несколько исключений можно обработать вместе, если нужно.
+else: # Необязательное выражение. Должно следовать за последним блоком except
+ print("Всё хорошо!") # Выполнится, только если не было никаких исключений
+
####################################################
@@ -330,23 +361,23 @@ except IndexError as e:
# Используйте def для создания новых функций
def add(x, y):
- print "x равен %s, а y равен %s" % (x, y)
+ print("x равен %s, а y равен %s" % (x, y))
return x + y # Возвращайте результат выражением return
# Вызов функции с аргументами
-add(5, 6) #=> prints out "x равен 5, а y равен 6" и возвращает 11
+add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвращает 11
-# Другой способ вызова функции с аргументами
+# Другой способ вызова функции — вызов с именованными аргументами
add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке.
-# Вы можете определить функцию, принимающую неизвестное количество аргументов
+# Вы можете определить функцию, принимающую изменяемое число аргументов
def varargs(*args):
return args
varargs(1, 2, 3) #=> (1,2,3)
-# А также можете определить функцию, принимающую изменяющееся количество
+# А также можете определить функцию, принимающую изменяемое число
# именованных аргументов
def keyword_args(**kwargs):
return kwargs
@@ -356,8 +387,8 @@ keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
# Если хотите, можете использовать оба способа одновременно
def all_the_args(*args, **kwargs):
- print args
- print kwargs
+ print(args)
+ print(kwargs)
"""
all_the_args(1, 2, a=3, b=4) выводит:
(1, 2)
@@ -368,11 +399,28 @@ all_the_args(1, 2, a=3, b=4) выводит:
# Используйте символ * для передачи кортежей и ** для передачи словарей
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
-all_the_args(*args) # эквивалент foo(1, 2, 3, 4)
-all_the_args(**kwargs) # эквивалент foo(a=3, b=4)
-all_the_args(*args, **kwargs) # эквивалент foo(1, 2, 3, 4, a=3, b=4)
+all_the_args(*args) # эквивалентно foo(1, 2, 3, 4)
+all_the_args(**kwargs) # эквивалентно foo(a=3, b=4)
+all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4)
-# Python имеет функции первого класса
+# Область определения функций
+x = 5
+
+def setX(num):
+ # Локальная переменная x — это не то же самое, что глобальная переменная x
+ x = num # => 43
+ print (x) # => 43
+
+def setGlobalX(num):
+ global x
+ print (x) # => 5
+ x = num # Глобальная переменная x теперь равна 6
+ print (x) # => 6
+
+setX(43)
+setGlobalX(6)
+
+# В Python есть функции первого класса
def create_adder(x):
def adder(y):
return x + y
@@ -388,7 +436,7 @@ add_10(3) #=> 13
map(add_10, [1,2,3]) #=> [11, 12, 13]
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
-# Мы можем использовать списки для удобного отображения и фильтрации
+# Для удобного отображения и фильтрации можно использовать списочные включения
[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
@@ -402,7 +450,11 @@ class Human(object):
# Атрибут класса. Он разделяется всеми экземплярами этого класса
species = "H. sapiens"
- # Обычный конструктор
+ # Обычный конструктор, вызывается при инициализации экземпляра класса
+ # Обратите внимание, что двойное подчёркивание в начале и в конце имени
+ # означает объекты и атрибуты, которые используются Python, но находятся
+ # в пространствах имён, управляемых пользователем.
+ # Не придумывайте им имена самостоятельно.
def __init__(self, name):
# Присваивание значения аргумента атрибуту класса name
self.name = name
@@ -423,17 +475,17 @@ class Human(object):
return "*grunt*"
-# Инстанцирование класса
+# Инициализация экземпляра класса
i = Human(name="Иван")
-print i.say("привет") # "Иван: привет"
+print(i.say("привет")) # Выводит: «Иван: привет»
-j = Human("Петр")
-print j.say("Привет") # "Петр: привет"
+j = Human("Пётр")
+print(j.say("Привет")) # Выводит: «Пётр: привет»
# Вызов метода класса
i.get_species() #=> "H. sapiens"
-# Присвоение разделяемому атрибуту
+# Изменение разделяемого атрибута
Human.species = "H. neanderthalensis"
i.get_species() #=> "H. neanderthalensis"
j.get_species() #=> "H. neanderthalensis"
@@ -448,12 +500,12 @@ Human.grunt() #=> "*grunt*"
# Вы можете импортировать модули
import math
-print math.sqrt(16) #=> 4
+print(math.sqrt(16)) #=> 4
# Вы можете импортировать отдельные функции модуля
from math import ceil, floor
-print ceil(3.7) #=> 4.0
-print floor(3.7) #=> 3.0
+print(ceil(3.7)) #=> 4.0
+print(floor(3.7)) #=> 3.0
# Можете импортировать все функции модуля.
# (Хотя это и не рекомендуется)
@@ -463,7 +515,7 @@ from math import *
import math as m
math.sqrt(16) == m.sqrt(16) #=> True
-# Модули в Python это обычные файлы с кодом python. Вы
+# Модули в Python — это обычные Python-файлы. Вы
# можете писать свои модули и импортировать их. Название
# модуля совпадает с названием файла.
@@ -472,18 +524,72 @@ math.sqrt(16) == m.sqrt(16) #=> True
import math
dir(math)
+####################################################
+## 7. Дополнительно
+####################################################
+
+# Генераторы помогут выполнить ленивые вычисления
+def double_numbers(iterable):
+ for i in iterable:
+ yield i + i
+
+# Генератор создаёт значения на лету.
+# Он не возвращает все значения разом, а создаёт каждое из них при каждой
+# итерации. Это значит, что значения больше 15 в double_numbers
+# обработаны не будут.
+# Обратите внимание: xrange — это генератор, который делает то же, что и range.
+# Создание списка чисел от 1 до 900000000 требует много места и времени.
+# xrange создаёт объект генератора, а не список сразу, как это делает range.
+# Если нам нужно имя переменной, совпадающее с ключевым словом Python,
+# мы используем подчёркивание в конце
+xrange_ = xrange(1, 900000000)
+
+# Будет удваивать все числа, пока результат не будет >= 30
+for i in double_numbers(xrange_):
+ print(i)
+ if i >= 30:
+ break
+
+
+# Декораторы
+# В этом примере beg оборачивает say
+# Метод beg вызовет say. Если say_please равно True,
+# он изменит возвращаемое сообщение
+from functools import wraps
+
+
+def beg(target_function):
+ @wraps(target_function)
+ def wrapper(*args, **kwargs):
+ msg, say_please = target_function(*args, **kwargs)
+ if say_please:
+ return "{} {}".format(msg, " Пожалуйста! У меня нет денег :(")
+ return msg
+
+ return wrapper
+
+
+@beg
+def say(say_please=False):
+ msg = "Вы не купите мне пива?"
+ return msg, say_please
+
+
+print(say()) # Вы не купите мне пива?
+print(say(say_please=True)) # Вы не купите мне пива? Пожалуйста! У меня нет денег :(
```
-## Хотите еще?
+## Хотите ещё?
### Бесплатные онлайн-материалы
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
* [Dive Into Python](http://www.diveintopython.net/)
-* [The Official Docs](http://docs.python.org/2.6/)
+* [Официальная документация](http://docs.python.org/2.6/)
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
* [Python Module of the Week](http://pymotw.com/2/)
+* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
### Платные
diff --git a/ru-ru/python3-ru.html.markdown b/ru-ru/python3-ru.html.markdown
new file mode 100644
index 00000000..637c0157
--- /dev/null
+++ b/ru-ru/python3-ru.html.markdown
@@ -0,0 +1,630 @@
+---
+language: python3
+lang: ru-ru
+contributors:
+ - ["Louie Dinh", "http://ldinh.ca"]
+ - ["Steven Basart", "http://github.com/xksteven"]
+translators:
+ - ["Andre Polykanine", "https://github.com/Oire"]
+filename: learnpython3-ru.py
+---
+
+Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из
+самых популярных языков. Я люблю его за понятный и доходчивый синтаксис — это
+почти что исполняемый псевдокод.
+
+С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)
+или louiedinh [at] [почтовый сервис Google]
+
+Замечание: Эта статья относится только к Python 3.
+Если вы хотите изучить Python 2.7, обратитесь к другой статье.
+
+```python
+# Однострочные комментарии начинаются с символа решётки.
+""" Многострочный текст может быть
+ записан, используя 3 знака " и обычно используется
+ в качестве встроенной документации
+"""
+
+####################################################
+## 1. Примитивные типы данных и операторы
+####################################################
+
+# У вас есть числа
+3 #=> 3
+
+# Математика работает вполне ожидаемо
+1 + 1 #=> 2
+8 - 1 #=> 7
+10 * 2 #=> 20
+
+# Кроме деления, которое по умолчанию возвращает число с плавающей запятой
+35 / 5 # => 7.0
+
+# Результат целочисленного деления округляется в меньшую сторону
+# как для положительных, так и для отрицательных чисел.
+5 // 3 # => 1
+5.0 // 3.0 # => 1.0 # работает и для чисел с плавающей запятой
+-5 // 3 # => -2
+-5.0 // 3.0 # => -2.0
+
+# Когда вы используете числа с плавающей запятой,
+# результатом будет также число с плавающей запятой
+3 * 2.0 # => 6.0
+
+# Остаток от деления
+7 % 3 # => 1
+
+# Возведение в степень
+2 ** 4 # => 16
+
+# Приоритет операций указывается скобками
+(1 + 3) * 2 #=> 8
+
+# Для логических (булевых) значений существует отдельный примитивный тип
+True
+False
+
+# Для отрицания используется ключевое слово not
+not True #=> False
+not False #=> True
+
+# Равенство — это ==
+1 == 1 #=> True
+2 == 1 #=> False
+
+# Неравенство — это !=
+1 != 1 #=> False
+2 != 1 #=> True
+
+# Ещё немного сравнений
+1 < 10 #=> True
+1 > 10 #=> False
+2 <= 2 #=> True
+2 >= 2 #=> True
+
+# Сравнения могут быть записаны цепочкой:
+1 < 2 < 3 #=> True
+2 < 3 < 2 #=> False
+
+# Строки определяются символом " или '
+"Это строка."
+'Это тоже строка.'
+
+# И строки тоже могут складываться! Хотя лучше этого не делайте.
+"Привет " + "мир!" #=> "Привет мир!"
+
+# Со строкой можно работать, как со списком символов
+"Это строка"[0] #=> 'Э'
+
+# Метод format используется для форматирования строк:
+"{0} могут быть {1}".format("строки", "форматированы")
+
+# Вы можете повторять аргументы форматирования, чтобы меньше печатать.
+"Ехал {0} через реку, видит {0} - в реке {1}! Сунул {0} руку в реку, {1} за руку греку цап!".format("грека", "рак")
+#=> "Ехал грека через реку, видит грека - в реке рак! Сунул грека руку в реку, рак за руку греку цап!"
+# Если вы не хотите считать, можете использовать ключевые слова.
+"{name} хочет есть {food}".format(name="Боб", food="лазанью")
+
+# Если ваш код на Python 3 нужно запускать также и под Python 2.5 и ниже,
+# вы также можете использовать старый способ форматирования:
+"%s можно %s %s способом" % ("строки", "интерполировать", "старым")
+
+# None является объектом
+None #=> None
+
+# Не используйте оператор равенства '==' для сравнения
+# объектов с None. Используйте для этого 'is'
+"etc" is None #=> False
+None is None #=> True
+
+# Оператор «is» проверяет идентичность объектов. Он не
+# очень полезен при работе с примитивными типами, но
+# зато просто незаменим при работе с объектами.
+
+# None, 0 и пустые строки/списки/словари приводятся к False.
+# Все остальные значения равны True
+bool(0) # => False
+bool("") # => False
+bool([]) #=> False
+bool({}) #=> False
+
+
+####################################################
+## 2. Переменные и коллекции
+####################################################
+
+# У Python есть функция Print
+print("Я Python. Приятно познакомиться!")
+
+# Необязательно объявлять переменные перед их инициализацией.
+# По соглашению используется нижний_регистр_с_подчёркиваниями
+some_var = 5
+some_var #=> 5
+
+# При попытке доступа к неинициализированной переменной
+# выбрасывается исключение.
+# Об исключениях см. раздел «Поток управления и итерируемые объекты».
+some_unknown_var # Выбрасывает ошибку именования
+
+# Списки хранят последовательности
+li = []
+# Можно сразу начать с заполненным списком
+other_li = [4, 5, 6]
+
+# Объекты добавляются в конец списка методом append
+li.append(1) # [1]
+li.append(2) # [1, 2]
+li.append(4) # [1, 2, 4]
+li.append(3) # [1, 2, 4, 3]
+# И удаляются с конца методом pop
+li.pop() #=> возвращает 3 и li становится равен [1, 2, 4]
+# Положим элемент обратно
+li.append(3) # [1, 2, 4, 3].
+
+# Обращайтесь со списком, как с обычным массивом
+li[0] #=> 1
+# Обратимся к последнему элементу
+li[-1] #=> 3
+
+# Попытка выйти за границы массива приведёт к ошибке индекса
+li[4] # Выдаёт IndexError
+
+# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax)
+# (Для тех, кто любит математику, это называется замкнуто-открытый интервал).
+li[1:3] #=> [2, 4]
+# Опускаем начало
+li[2:] #=> [4, 3]
+# Опускаем конец
+li[:3] #=> [1, 2, 4]
+# Выбираем каждый второй элемент
+li[::2] # =>[1, 4]
+# Переворачиваем список
+li[::-1] # => [3, 4, 2, 1]
+# Используйте сочетания всего вышеназванного для выделения более сложных кусков
+# li[начало:конец:шаг]
+
+# Удаляем произвольные элементы из списка оператором del
+del li[2] # [1, 2, 3]
+
+# Вы можете складывать списки
+li + other_li #=> [1, 2, 3, 4, 5, 6] — Замечание: li и other_li не изменяются
+
+# Объединять списки можно методом extend
+li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6]
+
+# Проверить элемент на вхождение в список можно оператором in
+1 in li #=> True
+
+# Длина списка вычисляется функцией len
+len(li) #=> 6
+
+
+# Кортежи — это такие списки, только неизменяемые
+tup = (1, 2, 3)
+tup[0] #=> 1
+tup[0] = 3 # Выдаёт TypeError
+
+# Всё то же самое можно делать и с кортежами
+len(tup) #=> 3
+tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
+tup[:2] #=> (1, 2)
+2 in tup #=> True
+
+# Вы можете распаковывать кортежи (или списки) в переменные
+a, b, c = (1, 2, 3) # a == 1, b == 2 и c == 3
+# Кортежи создаются по умолчанию, если опущены скобки
+d, e, f = 4, 5, 6
+# Обратите внимание, как легко поменять местами значения двух переменных
+e, d = d, e # теперь d == 5, а e == 4
+
+
+# Словари содержат ассоциативные массивы
+empty_dict = {}
+# Вот так описывается предзаполненный словарь
+filled_dict = {"one": 1, "two": 2, "three": 3}
+
+# Значения ищутся по ключу с помощью оператора []
+filled_dict["one"] #=> 1
+
+# Все значения в виде списка получаются с помощью метода keys().
+# Его вызов нужно обернуть в list(), так как обратно мы получаем
+# итерируемый объект, о которых поговорим позднее.
+list(filled_dict.keys()) # => ["three", "two", "one"]
+# Замечание: сохранение порядка ключей в словаре не гарантируется
+# Ваши результаты могут не совпадать с этими.
+
+# Все значения в виде списка можно получить с помощью values().
+# И снова нам нужно обернуть вызов в list(), чтобы превратить
+# итерируемый объект в список.
+list(filled_dict.values()) # => [3, 2, 1]
+# То же самое замечание насчёт порядка ключей справедливо и здесь
+
+# При помощи оператора in можно проверять ключи на вхождение в словарь
+"one" in filled_dict #=> True
+1 in filled_dict #=> False
+
+# Попытка получить значение по несуществующему ключу выбросит ошибку ключа
+filled_dict["four"] # KeyError
+
+# Чтобы избежать этого, используйте метод get
+filled_dict.get("one") #=> 1
+filled_dict.get("four") #=> None
+# Метод get также принимает аргумент по умолчанию, значение которого будет
+# возвращено при отсутствии указанного ключа
+filled_dict.get("one", 4) #=> 1
+filled_dict.get("four", 4) #=> 4
+
+# Метод setdefault вставляет пару ключ-значение, только если такого ключа нет
+filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5
+filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5
+
+# Удаляйте ключи из словаря с помощью оператора del
+del filled_dict["one"] # Удаляет ключ «one» из словаря
+
+
+# Множества содержат... ну, в общем, множества
+empty_set = set()
+# Инициализация множества набором значений.
+# Да, оно выглядит примерно как словарь… ну извините, так уж вышло.
+filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4}
+
+# Множеству можно назначать новую переменную
+filled_set = some_set
+
+# Добавление новых элементов в множество
+filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5}
+
+# Пересечение множеств: &
+other_set = {3, 4, 5, 6}
+filled_set & other_set #=> {3, 4, 5}
+
+# Объединение множеств: |
+filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
+
+# Разность множеств: -
+{1,2,3,4} - {2,3,5} #=> {1, 4}
+
+# Проверка на вхождение во множество: in
+2 in filled_set #=> True
+10 in filled_set #=> False
+
+
+####################################################
+## 3. Поток управления и итерируемые объекты
+####################################################
+
+# Для начала заведём переменную
+some_var = 5
+
+# Так выглядит выражение if. Отступы в python очень важны!
+# результат: «some_var меньше, чем 10»
+if some_var > 10:
+ print("some_var намного больше, чем 10.")
+elif some_var < 10: # Выражение elif необязательно.
+ print("some_var меньше, чем 10.")
+else: # Это тоже необязательно.
+ print("some_var равно 10.")
+
+
+# Циклы For проходят по спискам. Результат:
+ # собака — это млекопитающее
+ # кошка — это млекопитающее
+ # мышь — это млекопитающее
+for animal in ["собака", "кошка", "мышь"]:
+ # Можете использовать format() для интерполяции форматированных строк
+ print("{} — это млекопитающее".format(animal))
+
+"""
+«range(число)» возвращает список чисел
+от нуля до заданного числа
+Результат:
+ 0
+ 1
+ 2
+ 3
+"""
+for i in range(4):
+ print(i)
+
+"""
+Циклы while продолжаются до тех пор, пока указанное условие не станет ложным.
+Результат:
+ 0
+ 1
+ 2
+ 3
+"""
+x = 0
+while x < 4:
+ print(x)
+ x += 1 # Краткая запись для x = x + 1
+
+# Обрабатывайте исключения блоками try/except
+try:
+ # Чтобы выбросить ошибку, используется raise
+ raise IndexError("Это ошибка индекса")
+except IndexError as e:
+ # pass это просто отсутствие оператора. Обычно здесь происходит
+ # восстановление после ошибки.
+ pass
+except (TypeError, NameError):
+ pass # Несколько исключений можно обработать вместе, если нужно.
+else: # Необязательное выражение. Должно следовать за последним блоком except
+ print("Всё хорошо!") # Выполнится, только если не было никаких исключений
+
+# Python предоставляет фундаментальную абстракцию,
+# которая называется итерируемым объектом (an iterable).
+# Итерируемый объект — это объект, который воспринимается как последовательность.
+# Объект, который возвратила функция range(), итерируемый.
+filled_dict = {"one": 1, "two": 2, "three": 3}
+our_iterable = filled_dict.keys()
+print(our_iterable) #=> range(1,10). Это объект, реализующий интерфейс iterable
+
+# Мы можем проходить по нему циклом.
+for i in our_iterable:
+ print(i) # Выводит one, two, three
+
+# Но мы не можем обращаться к элементу по индексу.
+our_iterable[1] # Выбрасывает ошибку типа
+
+# Итерируемый объект знает, как создавать итератор.
+our_iterator = iter(our_iterable)
+
+# Итератор может запоминать состояние при проходе по объекту.
+# Мы получаем следующий объект, вызывая функцию __next__.
+our_iterator.__next__() #=> "one"
+
+# Он сохраняет состояние при вызове __next__.
+our_iterator.__next__() #=> "two"
+our_iterator.__next__() #=> "three"
+
+# Возвратив все данные, итератор выбрасывает исключение StopIterator
+our_iterator.__next__() # Выбрасывает исключение остановки итератора
+
+# Вы можете получить сразу все элементы итератора, вызвав на нём функцию list().
+list(filled_dict.keys()) #=> Возвращает ["one", "two", "three"]
+
+
+####################################################
+## 4. Функции
+####################################################
+
+# Используйте def для создания новых функций
+def add(x, y):
+ print("x равен %s, а y равен %s" % (x, y))
+ return x + y # Возвращайте результат выражением return
+
+# Вызов функции с аргументами
+add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвращает 11
+
+# Другой способ вызова функции — вызов с именованными аргументами
+add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке.
+
+# Вы можете определить функцию, принимающую изменяемое число аргументов
+def varargs(*args):
+ return args
+
+varargs(1, 2, 3) #=> (1,2,3)
+
+
+# А также можете определить функцию, принимающую изменяемое число
+# именованных аргументов
+def keyword_args(**kwargs):
+ return kwargs
+
+# Вызовем эту функцию и посмотрим, что из этого получится
+keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
+
+# Если хотите, можете использовать оба способа одновременно
+def all_the_args(*args, **kwargs):
+ print(args)
+ print(kwargs)
+"""
+all_the_args(1, 2, a=3, b=4) выводит:
+ (1, 2)
+ {"a": 3, "b": 4}
+"""
+
+# Вызывая функции, можете сделать наоборот!
+# Используйте символ * для передачи кортежей и ** для передачи словарей
+args = (1, 2, 3, 4)
+kwargs = {"a": 3, "b": 4}
+all_the_args(*args) # эквивалентно foo(1, 2, 3, 4)
+all_the_args(**kwargs) # эквивалентно foo(a=3, b=4)
+all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4)
+
+# Область определения функций
+x = 5
+
+def setX(num):
+ # Локальная переменная x — это не то же самое, что глобальная переменная x
+ x = num # => 43
+ print (x) # => 43
+
+def setGlobalX(num):
+ global x
+ print (x) # => 5
+ x = num # Глобальная переменная x теперь равна 6
+ print (x) # => 6
+
+setX(43)
+setGlobalX(6)
+
+# В Python функции — «объекты первого класса». Это означает, что их можно использовать наравне с любыми другими значениями
+def create_adder(x):
+ def adder(y):
+ return x + y
+ return adder
+
+add_10 = create_adder(10)
+add_10(3) #=> 13
+
+# Также есть и анонимные функции
+(lambda x: x > 2)(3) #=> True
+
+# Есть встроенные функции высшего порядка
+map(add_10, [1,2,3]) #=> [11, 12, 13]
+filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
+
+# Для удобного отображения и фильтрации можно использовать списочные включения
+[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
+[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
+
+####################################################
+## 5. Классы
+####################################################
+
+# Чтобы получить класс, мы наследуемся от object.
+class Human(object):
+
+ # Атрибут класса. Он разделяется всеми экземплярами этого класса
+ species = "H. sapiens"
+
+ # Обычный конструктор, вызывается при инициализации экземпляра класса
+ # Обратите внимание, что двойное подчёркивание в начале и в конце имени
+ # означает объекты и атрибуты, которые используются Python, но находятся
+ # в пространствах имён, управляемых пользователем.
+ # Не придумывайте им имена самостоятельно.
+ def __init__(self, name):
+ # Присваивание значения аргумента атрибуту класса name
+ self.name = name
+
+ # Метод экземпляра. Все методы принимают self в качестве первого аргумента
+ def say(self, msg):
+ return "{name}: {message}".format(name=self.name, message=msg)
+
+ # Метод класса разделяется между всеми экземплярами
+ # Они вызываются с указыванием вызывающего класса в качестве первого аргумента
+ @classmethod
+ def get_species(cls):
+ return cls.species
+
+ # Статический метод вызывается без ссылки на класс или экземпляр
+ @staticmethod
+ def grunt():
+ return "*grunt*"
+
+
+# Инициализация экземпляра класса
+i = Human(name="Иван")
+print(i.say("привет")) # Выводит: «Иван: привет»
+
+j = Human("Пётр")
+print(j.say("Привет")) # Выводит: «Пётр: привет»
+
+# Вызов метода класса
+i.get_species() #=> "H. sapiens"
+
+# Изменение разделяемого атрибута
+Human.species = "H. neanderthalensis"
+i.get_species() #=> "H. neanderthalensis"
+j.get_species() #=> "H. neanderthalensis"
+
+# Вызов статического метода
+Human.grunt() #=> "*grunt*"
+
+
+####################################################
+## 6. Модули
+####################################################
+
+# Вы можете импортировать модули
+import math
+print(math.sqrt(16)) #=> 4
+
+# Вы можете импортировать отдельные функции модуля
+from math import ceil, floor
+print(ceil(3.7)) #=> 4.0
+print(floor(3.7)) #=> 3.0
+
+# Можете импортировать все функции модуля.
+# (Хотя это и не рекомендуется)
+from math import *
+
+# Можете сокращать имена модулей
+import math as m
+math.sqrt(16) == m.sqrt(16) #=> True
+
+# Модули в Python — это обычные Python-файлы. Вы
+# можете писать свои модули и импортировать их. Название
+# модуля совпадает с названием файла.
+
+# Вы можете узнать, какие функции и атрибуты определены
+# в модуле
+import math
+dir(math)
+
+####################################################
+## 7. Дополнительно
+####################################################
+
+# Генераторы помогут выполнить ленивые вычисления
+def double_numbers(iterable):
+ for i in iterable:
+ yield i + i
+
+# Генератор создаёт значения на лету.
+# Он не возвращает все значения разом, а создаёт каждое из них при каждой
+# итерации. Это значит, что значения больше 15 в double_numbers
+# обработаны не будут.
+# Обратите внимание: range — это тоже генератор.
+# Создание списка чисел от 1 до 900000000 требует много места и времени.
+# Если нам нужно имя переменной, совпадающее с ключевым словом Python,
+# мы используем подчёркивание в конце
+range_ = range(1, 900000000)
+
+# Будет удваивать все числа, пока результат не превысит 30
+for i in double_numbers(xrange_):
+ print(i)
+ if i >= 30:
+ break
+
+
+# Декораторы
+# В этом примере beg оборачивает say
+# Метод beg вызовет say. Если say_please равно True,
+# он изменит возвращаемое сообщение
+from functools import wraps
+
+
+def beg(target_function):
+ @wraps(target_function)
+ def wrapper(*args, **kwargs):
+ msg, say_please = target_function(*args, **kwargs)
+ if say_please:
+ return "{} {}".format(msg, " Пожалуйста! У меня нет денег :(")
+ return msg
+
+ return wrapper
+
+
+@beg
+def say(say_please=False):
+ msg = "Вы не купите мне пива?"
+ return msg, say_please
+
+
+print(say()) # Вы не купите мне пива?
+print(say(say_please=True)) # Вы не купите мне пива? Пожалуйста! У меня нет денег :(
+
+```
+
+## Хотите ещё?
+
+### Бесплатные онлайн-материалы
+
+* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
+* [Dive Into Python](http://www.diveintopython.net/)
+* [Ideas for Python Projects](http://pythonpracticeprojects.com)
+* [Официальная документация](http://docs.python.org/3/)
+* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
+* [Python Module of the Week](http://pymotw.com/3/)
+* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
+
+### Платные
+
+* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
+* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
+* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
+