<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1835049761574940534</id><updated>2011-10-01T15:51:54.129+03:00</updated><category term='C++'/><category term='tbb'/><category term='qt'/><category term='parallel programming'/><category term='openmp'/><category term='python'/><category term='study'/><category term='latex'/><category term='life'/><title type='text'>Personal notes</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-2631496426754411329</id><published>2011-08-20T17:52:00.000+03:00</published><updated>2011-08-20T17:52:03.640+03:00</updated><title type='text'>Итераторы для начинающих. Путь С++</title><content type='html'>&lt;h4&gt;Предисловие&lt;/h4&gt;Данный пост предназначен исключительно для начинающих и не преследует цели рассказать всё об итераторах в С++. Так что если вы знаете о чём-нибудь вроде &lt;i&gt;iterator_traits&lt;&gt; &lt;/i&gt;, вам не будет интересно. Тем не менее, я надеюсь, что эта информация будет полезна для людей, которые раньше не сталкивались с итераторами.    &lt;h4&gt;Практическая задача&lt;/h4&gt;Предположим перед нами стоит простая задача - написать функцию, которая находила бы в массиве целых чисел максимальное значение и возвращала его индекс. Вы могли бы сделать это примерно так:  &lt;script src="http://www.xsnippet.tk/53002/embed"&gt;&lt;/script&gt;  Функция работает замечательно, но сразу видно её ограничение - она работает только с целыми значениями типа &lt;i&gt;int&lt;/i&gt;. Для поиска максимального значения в массива из элементов типа &lt;i&gt;float&lt;/i&gt; нам нужно написать такую же функцию, только изменив название типа. Мы знаем, что в таком случае, лучшие друзья С++-программиста - &lt;i&gt;шаблоны&lt;/i&gt; (templates). &lt;br&gt;&lt;br&gt;Универсальный вариант функции для поиска максимального элемента в массиве переменных произвольного типа выглядит так:  &lt;script src="http://www.xsnippet.tk/55003/embed"&gt;&lt;/script&gt;  Казалось бы, чего можно ещё желать. Но что если нам будет необходимо искать максимальный элемент не во всём массиве, а в лишь в определённой его части? &lt;br&gt;&lt;br&gt;Мы знаем, что массивы в С++ представляют собой линейно выделенный участок памяти, в котором по порядку расположены элементы. Более того имя массива является указателем на его первый элемент. Указатели и массивы неразрывно связаны - для доступа к элементам массива можно использовать адресную арифметику. &lt;br&gt;&lt;br&gt;Интервал элементов для нашей функции можно задавать при помощи двух указателей - указателя на &lt;b&gt;первый нужный&lt;/b&gt; элемент (begin) и указателем на элемент, &lt;b&gt;следующий за последним&lt;/b&gt; нужным элементом (end). Почему именно полуоткрытый интервал [begin; end)? Потому что это позволит формировать условие выхода из цикла очевидным образом. &lt;br&gt;&lt;br&gt;Реализация выглядит примерно так: &lt;script src="http://www.xsnippet.tk/55004/embed"&gt;&lt;/script&gt;  Используя этот вариант функции можно искать индекс максимального элемента во всём массиве, либо в какой-то его части: &lt;script src="http://www.xsnippet.tk/56002/embed"&gt;&lt;/script&gt;  &lt;h4&gt;А можно ли обобщить ещё больше?&lt;/h4&gt;Это всё хорошо, но, как известно, обычные массивы обладают рядом недостатков: нельзя изменить размер массива, нельзя вставить элемент в начало и т. д. Нам бы хотелось иметь возможность использовать другие структуры данных, такие как, например, &lt;a href="http://en.wikipedia.org/wiki/Linked_list"&gt;связный список&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Но в связном списке элементы не расположены в памяти по порядку - наша функция поиска индекса максимального элемента не может быть использована с этой структурой данных, хотя алгоритм остался прежним - необходимо последовательно пройти все элементы и сравнить их с сохранённым максимальным. &lt;br&gt;&lt;br&gt;Что действительно изменилось при переходе от массива к связному списку - это доступ к элементам. В массивах мы могли использовать стандартную адресную арифметику, тогда как для доступа к следующему элементу связного списка необходимо использовать указатель, который хранится в данном узле. &lt;b&gt;Доступ к элеметнам структуры данных жёстко закреплён в нашем алгоритме&lt;/b&gt;, а это значит, что для каждой новой структуры данных придётся реализовывать такой же алгоритм с небольшими отличиями в доступе к элементам - и это, конечно же, плохо. Необходимо уменьшить степень связи между алгоритмом и структурой данных, используя новую абстракцию.  &lt;br&gt;&lt;br&gt;Давайте ещё раз взглянем на нашу функцию: &lt;script src="http://www.xsnippet.tk/55004/embed"&gt;&lt;/script&gt;  Какие операции для доступа к элементам мы используем?  &lt;ol&gt;&lt;li&gt;&lt;b&gt;*&lt;/b&gt; - разыменование указателя - получения значения, которое хранится по адресу указателя;&lt;/li&gt;&lt;li&gt;&lt;b&gt;!=&lt;/b&gt; - сравнение двух указателей на неравенство (для определения конца интервала);&lt;/li&gt;&lt;li&gt;&lt;b&gt;++&lt;/b&gt; - инкремент - для перемещения указателя на следующий элемент.&lt;/li&gt;&lt;/ol&gt;Если бы мы могли передать в функцию max_element() вместо обычного указателя какой-нибудь объект, то определив для него данные операции, можно было бы заключить в них логику доступа к элементам связного списка. Это не сложно сделать, используя механизмы перегрузки операторов и шаблонов. Окончательный вариант функции выглядит так: &lt;script src="http://www.xsnippet.tk/59002/embed"&gt;&lt;/script&gt;  Вместо указателя используется новый параметр шаблона - класс Iterator.Так что же такое итератор? &lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;i&gt;Итератор&lt;/i&gt;&lt;/b&gt; - это специальный объект, который позволяет получить доступ к элементам структуры данных, не раскрывая её внутренного устройства, используя определённый абстрактный интерфейс.  &lt;br&gt;&lt;br&gt;В С++ в качестве интерфейса итераторов используется семантика указателей, но могли быть использованы обычные методы. Важно то, что данный интерфейс един для всех контейнеров - пользователи  работают именно с этим интерфейсом и ничего не знают о внутреннем устройтве контейнера, а значит такие алгоритмы как поиск максимального элемента могут быть обобщены для массивов, связных списков и т.д.  &lt;h4&gt;Пример своего итератора&lt;/h4&gt;Рассмотрим простейшую реализацию связного списка.  Реализация узла списка: &lt;script src="http://www.xsnippet.tk/54003/embed"&gt;&lt;/script&gt;  Реализация класса списка: &lt;script src="http://www.xsnippet.tk/56003/embed"&gt;&lt;/script&gt;  Реализован минимальный набор методов: &lt;ul&gt;&lt;li&gt;Инициализация структуры данных, освобождение памяти - LinkedList(), ~LinkedList().&lt;/li&gt;&lt;li&gt;Добавление элементов в начало и в конец списка - push_front(), push_back().&lt;/li&gt;&lt;li&gt;Доступ к элементам списка - методы, вовзращающие итераторы на начало и конец (как вы помните, для итераторов конец - это элемент следующий сразу за последним) - begin(), end(). &lt;/li&gt;&lt;/ul&gt;При помощи 2 итераторов можно пройти по всем элементам списка между ними.  Реализация итератора для списка: &lt;script src="http://www.xsnippet.tk/59003/embed"&gt;&lt;/script&gt;  Итератор инициализируется указателем на узел связного списка. Перегруженные операторы содержат логику перемещения между узлами и получения хранимого значения.  &lt;br&gt;&lt;br&gt;Давайте посмотрим, как можно использовать нашу функцию для поиска максимального элемента как в связном списке так и в обычном массиве: &lt;script src="http://www.xsnippet.tk/59004/embed"&gt;&lt;/script&gt;&lt;h4&gt;Заключение&lt;/h4&gt;Это, конечно же, лишь малая часть того, что нужно знать об итераторах. Мы рассмотрели лишь один вид итераторов, так называемые Forward Iterators, которые позволяют получать следующие элементы, двигаясь "прямо" (используется оператор ++). Существуют и другие виды итераторов, например, Bidirectional Iterators, которые также позволяют двигаться в обратном направлении (к операторам ++, !=, * добавляется оператор --), и другие.  &lt;br&gt;&lt;br&gt;В С++ в качестве интерфейса итераторов используется семантика указателей, но это просто условность - мог быть выбран любой другой интерфейс. Однако такая реализация позволяет использовать обычные указатели в качеcтве итераторов.  &lt;br&gt;&lt;br&gt;Итераторы играют очень важную роль в STL - они позволяют отделить алгоритмы от структур данных - являются прослойкой между ними. Таким образом алгоритмы могут быть обобщены для использования над различными структурами данных.  &lt;br&gt;&lt;br&gt;Исходный код примеров доступен здесь:&lt;a href="https://github.com/malor/iterators-source"&gt;https://github.com/malor/iterators-source&lt;/a&gt;  &lt;br&gt;&lt;br&gt;P.S. Отрывки кода внутри поста размещены на pastebin-сервисе &lt;a href="http://www.xsnippet.tk"&gt;XSnippet.tk&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-2631496426754411329?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/2631496426754411329/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=2631496426754411329' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/2631496426754411329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/2631496426754411329'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2011/08/blog-post.html' title='Итераторы для начинающих. Путь С++'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-8312233266250325643</id><published>2011-03-23T20:35:00.000+02:00</published><updated>2011-03-23T20:35:35.247+02:00</updated><title type='text'>Python. List Comprehensions and Generator Expressions</title><content type='html'>&lt;h2&gt;List Comprehensions&lt;/h2&gt;&lt;br /&gt;Предположим, у вас есть список целых чисел:&lt;br /&gt;&lt;pre class="prettyprint"&gt;numbers = [1, 2, 3, 4, 5, 6]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;И вам захотелось получить новый список, который бы содержал квадраты чисел из списка &lt;i&gt;numbers&lt;/i&gt;. Если вы новичок в Python, то могли бы решить эту задачу примерно так:&lt;br /&gt;&lt;pre class="prettyprint"&gt;squares = [] # создаём новый список&lt;br /&gt;    for i in numbers: # проходим в цикле по всем элементам&lt;br /&gt;        squares.append(i * i) # вычисляем квадрат и добавляем его в конец списка&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;В принципе, в этом нет ничего плохого, но в Python есть более удобная синтаксическая форма построения нового списка:&lt;br /&gt;&lt;pre class="prettyprint"&gt;squares = [i * i for i in numbers]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Давайте разберёмся, что это значит:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Использование скобок [ ] говорит нам о том, что происходит создание нового списка.&lt;/li&gt;&lt;li&gt;Правая часть записи ("for i in numbers") представляет собой обычный цикл &lt;i&gt;for&lt;/i&gt;: переменной &lt;i&gt;i&lt;/i&gt; по очереди присваивается значения из списка &lt;i&gt;numbers&lt;/i&gt;(1, 2, 3 ...).&lt;/li&gt;&lt;li&gt;Левая часть представляет собой произвольное выражение, возвращающее какое-то значение. В нашем случае вычисляется значение &lt;i&gt;i * i&lt;/i&gt;.&lt;/li&gt;&lt;li&gt;После того, как выражение будет вычислено, результат будет добавлен в конец создаваемого списка.&lt;/li&gt;&lt;li&gt;Операция будет выполнена для каждого значения &lt;i&gt;i&lt;/i&gt;, получаемого в цикле &lt;i&gt;for&lt;/i&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Такой способ создания списка называется &lt;i&gt;list comprehensions&lt;/i&gt;. Использование этой синтаксической особенности Python делает код более простым и читабельным (думаю, многие заметили, что &lt;i&gt;list comprehensions&lt;/i&gt; чем-то напоминают задание множеств элементов в дискретной математике).&lt;br /&gt;&lt;br /&gt;А что если нужно получить квадраты лишь чётных чисел? Опять таки, всё просто:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    squares = [i * i for i in numbers if i % 2 == 0]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Этот пример отличается от предыдущего лишь наличием оператора &lt;i&gt;if&lt;/i&gt;, после которого следует предикат &amp;mdash; какое-либо выражение (в том числе и вызов функции или метода), возвращающее значение типа &lt;i&gt;bool&lt;/i&gt;. В этом случае в создаваемый список будут добавлены &lt;b&gt;лишь&lt;/b&gt; те элементы, для которых значение предиката будет равно &lt;i&gt;True&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Generator Expression&lt;/h2&gt;&lt;br /&gt;У &lt;i&gt;list comprehensions&lt;/i&gt;, пожалуй, есть лишь один недостаток: происходит создание полного списка элементов в памяти, а это значит, что: для больших списков у вас может просто не хватить память, либо память будет использоваться неэффективно (например, если вы создаёте список, чтобы пройти по нему в цикле всего 1 раз).&lt;br /&gt;&lt;br /&gt;Для решения этой проблемы существуют &lt;i&gt;generator expressions&lt;/i&gt;. Синтаксически, они очень похожи на &lt;i&gt;list comprehensions&lt;/i&gt;, отличие лишь в используемых скобках:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    squares = (i * i for i in numbers if i % 2 == 0)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;В этом случае, &lt;i&gt;squares&lt;/i&gt; уже не будет списком чисел. Теперь это т.н. генератор (&lt;a href="http://wiki.python.org/moin/Generators"&gt;generator&lt;/a&gt;). Генератор реализует &lt;a href="http://docs.python.org/library/stdtypes.html#iterator-types"&gt;протокол итераторов&lt;/a&gt; и может быть использован в цикле &lt;i&gt;for&lt;/i&gt;. В этом случае следующее значение &lt;i&gt;generator expressions&lt;/i&gt; &lt;b&gt;будет генерироваться на каждой итерации цикла&lt;/b&gt;. В  данный момент времени будет существовать лишь один элемент, что значительно сокращает количество используемой памяти. Реализуется т.н. метод &lt;i&gt;lazy evalution&lt;/i&gt; &amp;mdash; новые значения генерируются только при необходимости, а не все одновременно.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Что почитать?&lt;/h2&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://diveintopython3.org/comprehensions.html"&gt;Dive Into Python 3: Comprehensions&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://wiki.python.org/moin/Generators"&gt;Generators and Generator Expressions&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-8312233266250325643?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/8312233266250325643/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=8312233266250325643' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/8312233266250325643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/8312233266250325643'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2011/03/python-list-comprehensions-and.html' title='Python. List Comprehensions and Generator Expressions'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-6817686534349952744</id><published>2011-03-17T13:58:00.009+02:00</published><updated>2011-03-17T21:24:06.117+02:00</updated><title type='text'>Python. Основы. Классы</title><content type='html'>&lt;p&gt;&lt;h2&gt;Класс. Экземпляр класса&lt;/h2&gt;&lt;br /&gt;Класс &amp;mdash; это пользовательский тип данных для создания &lt;i&gt;объектов&lt;/i&gt; (&lt;i&gt;objects&lt;/i&gt;). Объекты класса обычно называют &lt;i&gt;экземплярами&lt;/i&gt; этого класса (&lt;i&gt;class instances&lt;/i&gt;). Описание класса определяет поведение (методы) всех экземпляров класса.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;h2&gt;Everything is an object&lt;/h2&gt;&lt;br /&gt;В Python всё является объектами (т. н. &lt;a href="http://en.wikipedia.org/wiki/First-class_object"&gt;&lt;i&gt;first-class object&lt;/i&gt;&lt;/a&gt;). Это не значит, что у всех объектов есть методы и атрибуты. Это значит, что каждый объект может быть присвоен переменной, передан в функцию как аргумент, получен как возвращаемое значение функции и т.д. Т.е. нет никакой разницы в использовании объектов и, скажем, числа типа &lt;i&gt;int&lt;/i&gt; (которое, на самом деле, является объектом в Python).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;h2&gt;Создание классов и экземпляров классов. Методы и атрибуты&lt;/h2&gt;&lt;br /&gt;Создание нового класса осуществляется просто:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    class Employee:  # классы принято именовать с большой буквы&lt;br /&gt;&lt;br /&gt;        def __init__(self, age):  # "специальный" метод класса&lt;br /&gt;            self.age = age&lt;br /&gt;&lt;br /&gt;        def isEligible(self):  # метод класса&lt;br /&gt;            return True&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Методы класса (&lt;i&gt;instance methods&lt;/i&gt;, они же &lt;i&gt;member functions&lt;/i&gt; в C++, &lt;i&gt;class methods&lt;/i&gt; в Java) создаются как и обычные функции лишь за тем исключением, что первым аргументом они всегда принимают ссылку на экземпляр класса, для которого метод был вызван (как вы уже успели догадаться, известный всем &lt;i&gt;this&lt;/i&gt; в Python объявляется явно). На самом деле вместо &lt;i&gt;self&lt;/i&gt; могло быть использовано любое другое имя, но этого делать стоит, т.к. использование имя self является очень строгим &lt;a href="http://en.wikipedia.org/wiki/Coding_conventions"&gt;coding convention&lt;/a&gt; &amp;mdash; его игнорирование сделает ваш код менее читабельным для других программистов.&lt;br /&gt;&lt;br /&gt;В отличии от С++ и Java в Python атрибуты экземпляра класса (&lt;i&gt;instance variables&lt;/i&gt;, они же &lt;i&gt;member variables&lt;/i&gt; в С++, &lt;i&gt;class fields&lt;/i&gt; в Java) не нужно объявлять при создании класса. Python &amp;mdash; динамический язык. Атрибуты могут иметь произвольные имена и быть добавлены к экземпляру в любое время (&lt;b&gt;т. е. экземпляры одного и того же класса могут иметь различный набор атрибутов&lt;/b&gt;).&lt;br /&gt;&lt;br /&gt;Метод &lt;i&gt;__init__(self)&lt;/i&gt; не является обычным. Это &amp;quot;специальный метод&amp;quot;, на что намекают символы нижнего подчёркивания по бокам (существует ещё &lt;a href="http://diveintopython3.org/special-method-names.html"&gt;множество&lt;/a&gt; таких методов, которые используются, например, для перегрузки операторов). Метод &lt;i&gt;__init__(self)&lt;/i&gt; вызывается сразу после создания экземпляра класса и используется для задания атрибутов, которые должны иметь все экземпляры класса, т. е. очень похож на конструктор из С++ или Java.&lt;br /&gt;&lt;br /&gt;Создание экземпляра класса происходит так же, как если бы мы вызывали функцию с именем класса (при этом передаются необходимые для &lt;i&gt;__init__(self)&lt;/i&gt; аргументы):&lt;br /&gt;&lt;pre class="prettyprint"&gt;    # создание класса&lt;br /&gt;    class Employee:&lt;br /&gt;&lt;br /&gt;        def __init__(self, age):&lt;br /&gt;            self.age = age  # создание нового атрибута экземпляра с именем age&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    # cоздание экземпляра класса &lt;br /&gt;    # (обратите внимание: метод __init__(self) требует передачи аргумента age)&lt;br /&gt;    e = Employee(30)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Можно получать существующие атрибуты и добавлять новые:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    # создание экземпляра&lt;br /&gt;    e = Employee(30)&lt;br /&gt;&lt;br /&gt;    # чтение атрибута&lt;br /&gt;    print e.age&lt;br /&gt;    &lt;br /&gt;    # создание новых атрибутов&lt;br /&gt;    e.sex = 'male'&lt;br /&gt;    e.salary = 2500&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Вызов метода также не является чем-то необычным:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    e.isEligible()&lt;br /&gt;&lt;/pre&gt;Не смотря на то, что при объявлении метода &lt;i&gt;self&lt;/i&gt; указывался явно, при вызове метода этого делать не нужно &amp;mdash; интерпретатор сам подставит ссылку на экземпляр.&lt;br /&gt;&lt;br /&gt;Кроме атрибутов экземпляров классов, существуют непосредственно атрибуты класса. Они могут быть заданы при создании класса:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    class Employee:&lt;br /&gt;    &lt;br /&gt;        MAX_AGE = 80  # атрибут класса - он будет общим для всех экземпляров&lt;br /&gt;        &lt;br /&gt;        def __init__(self, age):&lt;br /&gt;            self.age = age # атрибут экземпляра - он у каждого экземпляра свой&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Либо после создания в любой момент выполнения программы:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    Employee.MAX_AGE = 90&lt;br /&gt;    Employee.MIN_AGE = 20  # опять таки, атрибут доступен из всех экземпляров&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Доступ к атрибутам класса осуществляется через имя класса либо через любой экземпляр класса:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    # доступ через имя класса&lt;br /&gt;    print Employee.MAX_AGE&lt;br /&gt;&lt;br /&gt;    e1 = Employee(20)&lt;br /&gt;    e2 = Employee(30)&lt;br /&gt;&lt;br /&gt;    # доступ через экземпляр&lt;br /&gt;    print e1.MAX_AGE&lt;br /&gt;    print e1.MAX_AGE == e2.MAX_AGE # True&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Т. е. атрибуты класса очень похожи на статические члены в C++ и Java.&lt;br /&gt;&lt;br /&gt;При обращении к атрибутам класса через экземпляр есть небольшая хитрость: если вы попытаетесь присвоить значение атрибуту класса, то ничего не выйдет &amp;mdash; вы просто создадите новый атрибут экземпляра:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    e1 = Employee(20)&lt;br /&gt;    e2 = Employee(30)&lt;br /&gt;    # для 2 экземпляров атрибут класса один и тот же&lt;br /&gt;    print e1.MAX_AGE == e2.MAX_AGE # True&lt;br /&gt;&lt;br /&gt;    # создаётся атрибут экземпляра, который "прячет"&lt;br /&gt;    # атрибут класса с таким же именем&lt;br /&gt;    e1.MAX_AGE = 50&lt;br /&gt;    # e1.MAX_AGE обращается к атрибуту экземпляра, а не класса!&lt;br /&gt;    print e1.MAX_AGE == e2.MAX_AGE # False&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;При использовании атрибутов классов обращайтесь к ним через имя класса &amp;mdash; это более очевидно и убережёт вас от неявных ошибок.&lt;br /&gt;&lt;br /&gt;Есть в Python и аналог статических методов класса в C++ и Java. Если у вас есть метод, который не должен вызываться для какого-то экземпляра класса конкретно, но, тем не менее, связан с классом, вы можете сделать его статическим:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    class A:&lt;br /&gt;        &lt;br /&gt;        @staticmethod&lt;br /&gt;        def f():&lt;br /&gt;            pass&lt;br /&gt;&lt;/pre&gt;(синтаксис немного необычный &amp;mdash; здесь используется декоратор, но объяснение принципов его работы выходит за рамки этого поста)&lt;br /&gt;&lt;br /&gt;Данный метод отличается от обычного лишь тем, что при его вызове не будет передаваться ссылка на экземпляр объекта &amp;mdash; &lt;i&gt;self&lt;/i&gt;. Вызов происходит через имя класса либо через экземпляр класса:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    # вызов через имя класса&lt;br /&gt;    A.f()&lt;br /&gt;&lt;br /&gt;    # вызов через экземпляр класса&lt;br /&gt;    a = A()&lt;br /&gt;    a.f()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Как и с атрибутами класса, предпочтительнее использовать имя класса, а не экземпляр.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;h2&gt;Наследование. Полиморфизм&lt;/h2&gt;&lt;br /&gt;Классы сами по себе не так интересны. Куда интереснее использование иерархий классов. Для того, чтобы использовать механизм наследования, достаточно указать имя базового класса при создании нового:&lt;br /&gt;&lt;pre class="prettyprint"&gt;    class Manager(Employee):&lt;br /&gt;        &lt;br /&gt;        def isEligible(self):     # методы могут быть переопределены в подклассах&lt;br /&gt;            return self.age &lt; 60&lt;br /&gt;&lt;br /&gt;    class Worker(Employee): &lt;br /&gt;        &lt;br /&gt;        def isEligible(self):&lt;br /&gt;            return self.age &lt; 35&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    class Secretary(Employee):&lt;br /&gt;        pass                      # подклассс может и не переопределять ничего&lt;br /&gt;&lt;/pre&gt;Если подкласс не определяет метод &lt;i&gt;__init__(self)&lt;/i&gt;, при инициализации экземпляра класса будет вызван соответствующий метод из суперкласса. Если же определяет, то необходимо явно вызывать метод инициализации из суперкласса:&lt;pre class="prettyprint"&gt;    class Manager(Employee):&lt;br /&gt;    &lt;br /&gt;        def __init__(self, age, employees):&lt;br /&gt;            Employee.__init__(self, age)   # обратите внимание, что указывается self&lt;br /&gt;            self.employees = employees&lt;br /&gt;&lt;/pre&gt;В Python, говоря терминами С++, все методы автоматически являются виртуальными:&lt;pre class="prettyprint"&gt;     m = Manager(50)&lt;br /&gt;     w = Worker(40)&lt;br /&gt;     s = Secretary(25)&lt;br /&gt;&lt;br /&gt;     for e in [m, w, s]:&lt;br /&gt;         print e.isEligible()&lt;br /&gt;&lt;/pre&gt;Для каждого из экземпляров будет вызван метод isEligible() из соответствующего ему класса. Никакой таблицы виртуальных функций здесь, конечно, нет: метод является атрибутом класса и может быть получен через оператор &lt;b&gt;&amp;quot;.&amp;quot;&lt;/b&gt; (для каждого подкласса, соответственно, будет получен &amp;quot;свой&amp;quot; метод).&lt;/p&gt;&lt;p&gt;&lt;h2&gt;Что почитать?&lt;/h2&gt;О классах кратко:&lt;ul&gt;&lt;li&gt;&lt;a href="http://diveintopython3.org/iterators.html"&gt;Dive Into Python 3&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://diveintopython.org/object_oriented_framework/index.html"&gt;Dive Into Python&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Более сложное чтиво:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html"&gt;Python Types and Objects&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cafepy.com/article/python_attributes_and_methods/"&gt;Python Attributes and Methods&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.python.org/tutorial/classes.html"&gt;Официальный мануал&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-6817686534349952744?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/6817686534349952744/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=6817686534349952744' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/6817686534349952744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/6817686534349952744'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2011/03/python.html' title='Python. Основы. Классы'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-1912412512218160340</id><published>2010-10-17T14:16:00.001+03:00</published><updated>2010-10-17T18:18:38.202+03:00</updated><title type='text'>Unicode in a Nutshell</title><content type='html'>&lt;h3&gt;Предисловие&lt;/h3&gt;&lt;br /&gt;Думаю, каждый из вас в своей жизни не раз сталкивался с проблемами, связанными с неправильным отображением текста на экране компьютера: будь то email'ы от ваших друзей, содержащие что-то вроде "оПХБЕР, ДПСФХЫЕ!" вместо "Привет, дружище!", web-страницы с повторяющимися знаками "?" вместо текста, странные символы вместо русского текста при выводе на консоль из простого Hello World, написанного на С++ и т. д. Проблемы такого рода связаны с тем, что многие программисты и сегодня не понимают, что такое Unicode и зачем он нужен.&lt;br /&gt;&lt;h3&gt;Немного истории&lt;/h3&gt;&lt;br /&gt;Когда появились первые компьютеры, возник вопрос о представлении в них текстовой информации. Компьютер ничего не знает о символах &lt;b&gt;'j'&lt;/b&gt;, &lt;b&gt;'!'&lt;/b&gt;, &lt;b&gt;'Б'&lt;/b&gt; и любых других. Компьютер не работает с символами - он работает с числами, представленными в виде последовательности байт (или одно байта). &lt;br /&gt;&lt;br /&gt;Чтобы компьютер "понимал" символы, было предложено присвоить каждому символу свой числовой код.&lt;br /&gt;Так родилась известная таблица &lt;a href="http://en.wikipedia.org/wiki/ASCII"&gt;ASCII&lt;/a&gt;, содержащая все буквы английского алфавита (в верхнем и нижнем регистре), знаки препинания и управляющие символы (переход на новую строку, возврат каретки и др.). Для этого понадобилось 128 различных кодов - от 0 до 127. Соответственно, для хранения кода символа нужен 1 байт, 7 бит которого используются, а старший всегда равен 0. Например, строка "HELLO" представляется в памяти как последовательность байт: 0x48 0x45 0x4C 0x4C 0x4F.&lt;br /&gt;&lt;br /&gt;И всё было хорошо, пока в компьютерах был лишь один язык. Когда же возникла необходимость добавить поддержку других языков, появились проблемы. Решение было очевидным: использовать свободные 128 кодов байта для кодирование нового алфавита, а первые 128 взять из ASCII. Проблема была в том, что каждый хотел использовать эти 128 кодов по-разному (например для разных языков, ведь 128 кодов не хватало для хранения нескольких алфавитов). Так возникло понятие кодовых страниц (&lt;a href="http://en.wikipedia.org/wiki/Code_page"&gt;code pages&lt;/a&gt; - они же "кодировки"). Каждая кодовая страница позволяет представить символы таблицы ASCII, а также ещё 1-2 языка (как например &lt;a href="http://en.wikipedia.org/wiki/KOI8-U"&gt;KOI8-U&lt;/a&gt;, которая хранит коды для символов английского, русского и украинского алфавитов, управляющие символы и знаки препинания). Такие кодировки были названы 8-битными, т.к. для кодирования 1 символа использовался 1 байт.&lt;br /&gt;&lt;br /&gt;Для того, чтобы правильно прочитать текст, нужно знать, в какой кодовой странице он представлен: байты остаются байтами и по-прежнему представляют собой одно и то же число, только это число в различных кодовых таблицах может указывать на совершенно разные символы. Отсюда вытекает важное утверждение: &lt;b&gt;текст не представляет собой никакой ценности, если неизвестно, какой кодировкой он представлен&lt;/b&gt;(Joel Spolsky). Это просто набор байт, который может означать, в общем случае, что угодно. Поэтому если мой друг присылает мне письмо, содержащие слово "Привет" в кодировке CP-1251 (0xCF 0xF0 0xE8 0xE2 0xE5 0xF2), а кодировка моей системы KOI8-R, то я прочитаю его как: "оПХБЕР".&lt;br /&gt;&lt;br /&gt;Пока люди работали на своих машинах и обменивались информацией сравнительно редко, с кодовыми страницами можно было мирится. С появлением Internet всё изменилось. Необходимо было новое решение, способное облегчить обмен информацией. Так возник Unicode.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Unicode&lt;/h3&gt;&lt;br /&gt;Unicode - это стандарт, описывающий представление и работу с текстовой информацией в компьютерных системах. Unicode позволяет по-иному взглянуть на представление символов в виде чисел:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Во-первых&lt;/b&gt;, в стандарт Unicode входят символы алфавитов всех языков мира.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Во-вторых&lt;/b&gt;, каждому символу соответствует уникальное число, называемое &lt;b&gt;Unicode code point&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;В-третьих&lt;/b&gt;, числовое значение символа ещё не говорит, как это число представляется в памяти компьютера в виде последовательности байт.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;В-четвёртых&lt;/b&gt;, т.к. стандарт Unicode включает в себя более 107000 символов, то 1 байта явно не хватит для представления символа. И хотя первые стандарты Unicode позиционировали систему как 16-битную "классическую" кодировку (которой бы хватало для представления 65536 символов), в настоящее время это не так. &lt;b&gt;Unicode - это не 16-битная кодировка&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Отсюда следует важный вывод: мы больше не может проводить прямое соответствие между символом и его значением в виде какого-то байта, как это было в "классических" кодировках. &lt;b&gt;Байты - это байты, символы - это абстракция.&lt;/b&gt; (Mark Pilgrim, 'Dive Into Python 3').&lt;br /&gt;&lt;br /&gt;Каждому символу в Unicode соответствует &lt;b&gt;code point&lt;/b&gt;. Это просто число - ни больше, ни меньше. Представлением этого code point в виде последовательности байт в памяти занимаются &lt;b&gt;кодировки Unicode&lt;/b&gt;, такие как &lt;b&gt;UTF-8&lt;/b&gt;, &lt;b&gt;UTF-16&lt;/b&gt;, &lt;b&gt;UTF-32&lt;/b&gt; (а также менее известные &lt;b&gt;UTF-1&lt;/b&gt;, &lt;b&gt;UTF-7&lt;/b&gt;). Каждая из них имеет свои достоинства и недостатки, являющиеся результатом компромиссов между скоростью работы и потреблением памяти.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;UTF-32&lt;/h3&gt;Самая простая кодировка. Представляет каждый code point любого символа Unicode в виде последовательности из 4 байт. Это означает, что любой ваш текст в "классической" кодировке, при переводе в кодировку UTF-32 станет занимать в 4 раза больше места! Не многовато ли? Естественно, это очень нерационально, поэтому никто так не делает. Для чего же тогда нужна UTF-32? UTF-32 позволяет удобно представить символы Unicode внутри компьютерной программы, упрощая и ускоряя работу со строками (размер кода каждого символа фиксирован, поэтому доступ к i-ому символу в строке выполняется со сложностью O(1), т.к. делается простой отступ по адресу).&lt;br /&gt;&lt;br /&gt;К сожалению, у UTF-32 есть и другие недостатки. Для кодирования любого символа используются 4 байта, поэтому для символов со значениями кодов 0-127 будет записано 3 байта со значением 0. К сожалению, старый С-код предполагает работу со строками, где байт '0' означает символ конца строки - такой код не сможет работать со строками в UTF-32.&lt;br /&gt;&lt;br /&gt;Помимо этого возникает вопрос, а как представлять 4-байтовое целое число - в формате &lt;a href="http://en.wikipedia.org/wiki/Endianness#Big-endian"&gt;big-endian&lt;/a&gt; или &lt;a href="http://en.wikipedia.org/wiki/Endianness#Little-endian"&gt;little-endian&lt;/a&gt; - должен ли символ 'А' (U+0041) быть представлен как 0x0 0x0 0x0 0x41 или же как 0x41 0x0 0x0 0x0. Оказывается, он может представляться и так, и так. Как же тогда определить, какой порядок байт используется? Для этого перед UTF-32 строкой/текстовым файлом вставляется специальный символ &lt;b&gt;BOM (byte order mark)&lt;/b&gt; - U+FEFF. Если вместо U+FEFF был прочитан символ U+FFFE, значит данный текст закодирован в UTF-32 с другим порядком байт, и необходимо инвертировать порядок байт во всех последующих символах при чтении.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;UTF-16&lt;/h3&gt;В UTF-16 для кодирование одного символа используется 2 байта, что позволяет закодировать 65536 первых символов Unicode из так называемой &lt;b&gt;BMP&lt;/b&gt; - &lt;a href="http://en.wikipedia.org/wiki/Basic_Multilingual_Plane#Basic_Multilingual_Plane"&gt;Basic Multilingual Plane&lt;/a&gt;. Но стандарт включает в себя около 100000 символов, как же представляются остальные? С помощью 4 байт, используя т.н. &lt;b&gt;surrogate pairs&lt;/b&gt;. Т.е. &lt;b&gt;UTF-16 не является кодировкой с фиксированным размером кода символа&lt;/b&gt;. UTF-16 позволяет более экономно использовать память по сравнению с UTF-32, но не лишена 2 её недостатков: порядок байт по-прежнему имеет значение, и старый код также не может работать со строками в UTF-16. Кроме того нельзя гарантировать доступ к i-ому cимволу строки со сложностью O(1), т.к. в строке могут содержаться символы, занимающие различное количество байт.&lt;br /&gt;&lt;br /&gt;Не смотря на имеющиеся недостатки, UTF-16 широко используется, в частности для представления символов в языках C#/Java, классе QChar фреймворка Qt.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;UTF-8&lt;/h3&gt;&lt;br /&gt;Кодировка UTF-8 решает проблемы своих предшественниц. При кодировании символов Unicode при помощи UTF-8 для code point'ов в промежутке [0, 127] используется 1 байт, для остальных символов - 2, 3 либо 4 байта по мере увеличения значения code point. Это означает, что:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Текст, закодированный в ASCII, является также текстом, закодированным в UTF-8.&lt;/li&gt;&lt;li&gt;Наиболее эффективно используется память. Для английского алфавита, управляющих символов и знаков препинания - не хуже чем ASCII (или любая другая 8-битная кодировка), для остальных - на равне с UTF-16 либо лучше.&lt;/li&gt;&lt;li&gt;Старый код работает со строками в UTF-8.&lt;/li&gt;&lt;li&gt;Порядок байт не имеет значения - текст всегда будет прочитан правильно.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;К сожалению, т.к. UTF-8 является кодировкой с переменной длиной кода символа, это означает, что доступ к i-ому элементу строки производится со сложностью O(n).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Выводы&lt;/h3&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Unicode - не 16-битная кодировка.&lt;/li&gt;&lt;li&gt;Символы - это абстракция, компьютеры работают с байтами - не с символами.&lt;/li&gt;&lt;li&gt;Кодировка - это отображение(таблица соответствия, map) символа его представлению в виде последовательности байт(либо одного байта в случае использования 8-битной кодировки, например, ASCII или CP-1251).&lt;/li&gt;&lt;li&gt;Стандарт Unicode ставит каждому символу любого алфавита мира в соответствие уникальное число, называемое code point.&lt;/li&gt;&lt;li&gt;Представлением code point в виде последовательности байт занимаются кодировки Unicode: UTF-8, UTF-16, UTF-32, каждая из которых имеет свои достоинства и недостатки.&lt;/li&gt;&lt;li&gt;UTF-16/UTF-32 более эффективны с точки зрения скорости обработки символов - они используются для внутрипрограммного представления символов Unicode.&lt;/li&gt;&lt;li&gt;UTF-8 более эффективна с точки зрения количества используемой памяти, возможности работы со старым кодом, отсутствия проблем с порядком байт. Она используется для хранения текстовой информации и передачи её между различными компьютерами.&lt;/li&gt;&lt;li&gt;Текст не представляет собой ценности, если неизвестно, в какой кодировке он представлен.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h3&gt;Использованная литература&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.joelonsoftware.com/printerFriendly/articles/Unicode.html"&gt;The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://diveintopython3.org/strings.html"&gt;Dive Into Python 3&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://evanjones.ca/unicode-in-c.html"&gt;Using Unicode in C/C++&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-1912412512218160340?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/1912412512218160340/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=1912412512218160340' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/1912412512218160340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/1912412512218160340'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2010/10/unicode-in-nutshell.html' title='Unicode in a Nutshell'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-5778741243672327560</id><published>2010-10-07T01:19:00.001+03:00</published><updated>2010-10-07T01:25:50.077+03:00</updated><title type='text'>C++. Преобразование числа в строку</title><content type='html'>Часто возникает необходимость иметь представление числа в виде строки (например, если есть функция, которая выводит заданную строку на экран, и нужно вывести число). Обычно для этого используют &lt;b&gt;С&lt;/b&gt;-шные фунции &lt;b&gt;snprintf&lt;/b&gt;(&lt;b&gt;wsnprintf&lt;/b&gt;) или, что ещё хуже, &lt;b&gt;sprintf&lt;/b&gt;(&lt;b&gt;wsprintf&lt;/b&gt;). Это очень неудобно по нескольким причинам:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Нужно знать, сколько памяти необходимо выделить (пусть даже в виде массива &lt;b&gt;char&lt;/b&gt;/&lt;b&gt;wchar_t&lt;/b&gt; на стеке).&lt;/li&gt;&lt;li&gt;Для разных числовых типов данных необходимо применять различные спецификаторы.&lt;/li&gt;&lt;li&gt;Нужно помнить формат спецификаторов.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;В &lt;b&gt;С++&lt;/b&gt; есть красивое решение с использованием строковых потоков, которое я подсмотрел &lt;a href="http://www.research.att.com/~bs/bs_faq2.html#int-to-string"&gt;у Строуструпа&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;std::stringstream s;&lt;br /&gt;int a = 42;&lt;br /&gt;&lt;br /&gt;s &lt;&lt; a;&lt;br /&gt;std::string str = s.str();&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Для получения &lt;b&gt;С&lt;/b&gt;-строки можно просто вызвать метод &lt;b&gt;c_str&lt;/b&gt;() класса &lt;b&gt;std::string&lt;/b&gt;. Для &lt;b&gt;wchar_t&lt;/b&gt; применяются классы &lt;b&gt;std::wstringstream&lt;/b&gt; и &lt;b&gt;std::wstring&lt;/b&gt; соответственно. При необходимости можно перегрузить оператор &lt;b&gt; &amp;lt;&amp;lt; &lt;/b&gt; для своего класса и преобразовывать какие-либо данные в строку таким же образом.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-5778741243672327560?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/5778741243672327560/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=5778741243672327560' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/5778741243672327560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/5778741243672327560'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2010/10/c.html' title='C++. Преобразование числа в строку'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-1128777030846705329</id><published>2010-08-01T11:37:00.000+03:00</published><updated>2010-08-01T11:37:48.159+03:00</updated><title type='text'>Writing C-code in Python</title><content type='html'>В настоящее время всё больше программистов выбирают &lt;b&gt;Python&lt;/b&gt; в качестве 2/3/etc языка для изучения. Их "родными" языками обычно являются &lt;b&gt;C/C++/Java/C#&lt;/b&gt;. Имея за плечами определённый опыт программирования на любом из этих языков, освоение нового языка не кажется сложной задачей.&lt;br /&gt;Алгоритмические конструкции в большинстве современных языков достаточно похожи, остаётся лишь "привыкнуть" к новому синтаксису. К сожалению, не всё так просто.&lt;br /&gt;&lt;br /&gt;Язык программирования - это не просто синтаксис, а ещё и набор определённых подходов, особенностей, методов решения практических задач. И далеко не всегда, методы, которые хорошо работают в привычном для вас языке, будут так же работать в другом языке, который вы хотите изучить. Именно опыт работы с каким-либо из языков программирования может сыграть с вами злую шутку при изучении &lt;b&gt;Python&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Код на &lt;b&gt;Python&lt;/b&gt; призван быть лаконичным и читабельным. Для достижения данных целей используются различные особенности синтаксиса языка (принудительные отступы вместо привычных фигурных скобок, etc). К сожалению, программисты на других языках часто осваивают лишь синтаксис &lt;b&gt;Python&lt;/b&gt;, забывая о необходимости ознакомления со всеми этими особенностями. А потом они начинают писать ужасный код. И хотя это код является рабочим, его точно нельзя охарактеризовать как &lt;a href="http://faassen.n--tree.net/blog/view/weblog/2005/08/06/0"&gt;pythonic&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Я бы хотел выделить наиболее часто допускаемые ошибки:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Циклы for&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Неправильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;for i in range(len(nums)):&lt;br /&gt;    print nums[i]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;msg = 'hello'&lt;br /&gt;for i in range(len(msg)):&lt;br /&gt;    print msg[i]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Правильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;for i in nums:&lt;br /&gt;    print i&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;msg = 'hello'&lt;br /&gt;for c in msg:&lt;br /&gt;    print c&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Мораль&lt;/b&gt;:&lt;br /&gt;В Python для доступа к элементам списков и строк используются &lt;a href="http://ru.wikipedia.org/wiki/%D0%98%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80"&gt;итераторы&lt;/a&gt; (справедливо и для словарей, множеств, кортежей и др.). При прохождении по всем элементам контейнера нет необходимости в использовании индексной выборки.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;hrule&gt;&lt;li&gt;&lt;b&gt;Проверка списка(строки, словаря, etc) на пустоту&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Неправильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = []&lt;br /&gt;if len(nums) == 0:&lt;br /&gt;    print 'The list is empty!'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;str = ''&lt;br /&gt;if len(str) == 0:&lt;br /&gt;    print 'The string is empty!'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Правильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = []&lt;br /&gt;if not nums:&lt;br /&gt;    print 'The list is empty!'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;str = ''&lt;br /&gt;if not str:&lt;br /&gt;    print 'The string is empty!'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Мораль&lt;/b&gt;:&lt;br /&gt;Не нужно загрязнять код проверками длины. Каждый "объект-контейнер" (если можно так сказать), является &lt;b&gt;False&lt;/b&gt; (при проверке в условном операторе &lt;b&gt;if&lt;/b&gt;), если он пуст, &lt;b&gt;True&lt;/b&gt; - если не пуст.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Проверка вхождения элемента в список&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Неправильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;for i in nums:&lt;br /&gt;    if i == 2:&lt;br /&gt;        print 'Found!'&lt;br /&gt;        break&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;info = {'server': '127.0.0.1', 'port': 80}&lt;br /&gt;for key in info.keys():&lt;br /&gt;    if key == 'port':&lt;br /&gt;        # do something&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Правильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;if 2 in nums:&lt;br /&gt;    print 'Found!'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;info = {'server': '127.0.0.1', 'port': 80}&lt;br /&gt;if key in info:&lt;br /&gt;    # do something&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Мораль&lt;/b&gt;:&lt;br /&gt;Для проверки вхождения элемента в "контейнер"(строку, список, кортеж, множество, словарь, пользовательские типы) используется оператор &lt;b&gt;in&lt;/b&gt;: лаконично, удобно, просто, быстро.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Multiple assignment&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Неправильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;a = 1&lt;br /&gt;b = 2&lt;br /&gt;&lt;br /&gt;# swap values of variables a and b&lt;br /&gt;temp = a&lt;br /&gt;a = b      # 2&lt;br /&gt;b = temp   # 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;SUNDAY  = 0&lt;br /&gt;MONDAY  = 1&lt;br /&gt;TUESDAY = 2&lt;br /&gt;# ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Правильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;a = 1&lt;br /&gt;b = 2&lt;br /&gt;&lt;br /&gt;# swap values of variables a and b&lt;br /&gt;a, b = b, a&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;SUNDAY, MONDAY, TUESDAY, WEDNESDAY, \&lt;br /&gt;THURSDAY, FRIDAY, SATURDAY = range(7)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Мораль&lt;/b&gt;: Благодаря синтаксическим особенностям &lt;b&gt;Python&lt;/b&gt; (наличие кортежей) возможным является присвоение нескольких значений одновременно, что можно использовать, например, для обмена значений двух переменных без использования третьей.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Стандартная библиотека&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Неправильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;dir = '/home/user/'&lt;br /&gt;name = '1.txt'&lt;br /&gt;&lt;br /&gt;with open(dir + name) as f:&lt;br /&gt;    # do something&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;allGreatherThanZero = True&lt;br /&gt;&lt;br /&gt;for num in nums:&lt;br /&gt;    if num &lt;= 0:&lt;br /&gt;        allGreatherThanZero = False&lt;br /&gt;        break&lt;br /&gt;&lt;br /&gt;if allGreatherThanZero:&lt;br /&gt;    # do something&lt;br /&gt;&lt;/pre&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;&lt;br /&gt;sum = 0&lt;br /&gt;for num in nums:&lt;br /&gt;    sum += num&lt;br /&gt;&lt;br /&gt;print sum&lt;br /&gt;&lt;/pre&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;&lt;br /&gt;min = nums[0]&lt;br /&gt;for num in nums[1:]:&lt;br /&gt;    if num &lt; min:&lt;br /&gt;        min = num&lt;br /&gt;&lt;br /&gt;print min&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Правильно&lt;/b&gt;:&lt;pre class="prettyprint"&gt;import os&lt;br /&gt;&lt;br /&gt;dir = '/home/user/'&lt;br /&gt;name = '1.txt'&lt;br /&gt;&lt;br /&gt;with open(os.path.join(dir, name)) as f:&lt;br /&gt;    # do something&lt;br /&gt;&lt;/pre&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;&lt;br /&gt;if all(num &gt; 0 for num in nums):&lt;br /&gt;    # do something&lt;br /&gt;&lt;/pre&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;&lt;br /&gt;print sum(nums)&lt;br /&gt;&lt;/pre&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3]&lt;br /&gt;&lt;br /&gt;print min(nums)&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Мораль&lt;/b&gt;:Использование функций стандартной библиотеки вместо своих велосипедов приводит к уменьшению количества ошибок, повышению читабельности и сокращению размера кода. Стандартная библиотека &lt;b&gt;Python&lt;/b&gt; обладает огромными возможностями и хорошо документирована - пользуйтесь.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Преобразование списка в строку&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Неправильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;colors = ['red', 'green', 'blue']&lt;br /&gt;&lt;br /&gt;str = 'RGB stands for '&lt;br /&gt;for color in colors:&lt;br /&gt;    str += ', ' + color&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Правильно&lt;/b&gt;:&lt;br /&gt;&lt;pre class="prettyprint"&gt;colors = ['red', 'green', 'blue']&lt;br /&gt;&lt;br /&gt;str = 'RGB stands for ' + ', '.join(colors)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Мораль&lt;/b&gt;:&lt;br /&gt;Использование метода &lt;b&gt;join&lt;/b&gt; делает код более читабельным и лаконичным, к томе же работает такой код быстрее, чем при использовании конкатенации строк.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;List comprehensions&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Неправильно:&lt;/b&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3, 4, 5]&lt;br /&gt;&lt;br /&gt;squares = []&lt;br /&gt;for num in nums:&lt;br /&gt;    squares.append(num ** 2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;import os&lt;br /&gt;import glob&lt;br /&gt;&lt;br /&gt;extensions = ['.mp3', '.ogg']&lt;br /&gt;&lt;br /&gt;fileList = glob.glob('*.*')&lt;br /&gt;&lt;br /&gt;audio = []&lt;br /&gt;for f in fileList:&lt;br /&gt;    if os.path.splitext(f)[1] in extensions:&lt;br /&gt;        audio.append(os.path.join(os.getcwd(), f))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Правильно:&lt;/b&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;nums = [1, 2, 3, 4, 5]&lt;br /&gt;&lt;br /&gt;squares = [num ** 2 for num in nums]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;import os&lt;br /&gt;import glob&lt;br /&gt;&lt;br /&gt;extensions = ['.mp3', '.ogg']&lt;br /&gt;&lt;br /&gt;fileList = glob.glob('*.*')&lt;br /&gt;&lt;br /&gt;audio = [os.path.join(os.getcwd(), f)&lt;br /&gt;         for f in fileList &lt;br /&gt;         if os.path.splitext(f)[1] in extensions]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Мораль:&lt;/b&gt;&lt;br /&gt;&lt;b&gt;List comprehensions&lt;/b&gt; - ещё одна из синтаксических особенностей &lt;b&gt;Python&lt;/b&gt;, позволяющая сделать код более читабельным и оптимальным.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Изучая новый язык, постарайтесь не перетягивать сюда свои вредные привычки из других языков программирования. Потратьте время на освоение новых подходов и методов решения задач. Нужно не просто перейти на использование нового синтаксиса, а "приобщиться к культуре" языка. Приложив необходимые усилия вы начнёте писать код, который действительно можно будет назвать &lt;b&gt;pythonic&lt;/b&gt;.&lt;br&gt;&lt;b&gt;Следует почитать:&lt;/b&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://diveintopython.org/"&gt;Mark Pilgrim 'Dive Into Python'&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://diveintopython3.org/"&gt;Mark Pilgrim 'Dive Into Python 3'&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;PEP 8 - Style Guide for Python Code&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://jaynes.colorado.edu/PythonIdioms.html"&gt;Python Idioms and Efficiency&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.siafoo.net/article/52"&gt;Python Tips, Tricks, and Hacks&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.python.org/dev/peps/pep-0020/"&gt;PEP 20 - The Zen of Python&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-1128777030846705329?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/1128777030846705329/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=1128777030846705329' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/1128777030846705329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/1128777030846705329'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2010/08/writing-c-code-in-python.html' title='Writing C-code in Python'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-6400253429425066229</id><published>2010-02-14T20:57:00.001+02:00</published><updated>2010-02-14T22:17:20.572+02:00</updated><title type='text'>Students Coffee &amp; Code #2. Unicode</title><content type='html'>Сегодня провели ещё один &lt;b&gt;SC&amp;amp;C&amp;nbsp; &lt;/b&gt;- выкладываю свою презентацию по &lt;b&gt;Unicode&lt;/b&gt; и примеры. Может когда-нибудь напишу полноценную статью. Критика и предложения приветствуются.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;P.S.&lt;/b&gt; В презентации всего не объяснишь - обязательно прочитайте статью &lt;b&gt;Joel'a Spolsky&lt;/b&gt; по ссылке в конце. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;slides&lt;/b&gt;: &lt;a href="http://docs.google.com/present/edit?id=0Ac4bqn8_YtynZGZncjc3N18xM2c3YmJjZ2hw&amp;amp;hl=en"&gt;http://docs.google.com/present/edit?id=0Ac4bqn8_YtynZGZncjc3N18xM2c3YmJjZ2hw&amp;amp;hl=en&lt;/a&gt;&lt;br /&gt;&lt;b&gt;code&lt;/b&gt;: &lt;a href="http://gitorious.org/amd4ever/my-git/trees/master/coffee/unicode"&gt;http://gitorious.org/amd4ever/my-git/trees/master/coffee/unicode&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-6400253429425066229?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/6400253429425066229/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=6400253429425066229' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/6400253429425066229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/6400253429425066229'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2010/02/students-coffee-code-2-unicode.html' title='Students Coffee &amp; Code #2. Unicode'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-404111720543355498</id><published>2010-02-10T09:38:00.002+02:00</published><updated>2010-02-10T18:33:22.594+02:00</updated><title type='text'>Blog updates</title><content type='html'>Решил немного обновить блог:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Перевёл его на новый домен: &lt;a href="http://www.amd4ever.org.ua/"&gt;http://www.amd4ever.org.ua&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Удалил почти все старые посты. Почему? Во-первых, там практически не было полезной информации. Во-вторых, практически все ссылки на код были либо на &lt;b&gt;showmecode.com&lt;/b&gt;(который приказал долго жить), либо на мой старый &lt;b&gt;git&lt;/b&gt;, в-третьих - там было много откровенно плохого и бесполезного кода.&lt;/li&gt;&lt;/ol&gt;В ближайшее время планирую написать о чём-нибудь полезном (в частности о &lt;b&gt;Unicode&lt;/b&gt; и &lt;b&gt;LaTeX&lt;/b&gt;), а также о своих программах, имеющих хоть какую-нибудь практическую ценность.&lt;br /&gt;&lt;ol&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-404111720543355498?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/404111720543355498/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=404111720543355498' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/404111720543355498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/404111720543355498'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2010/02/blog-updates.html' title='Blog updates'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1835049761574940534.post-7871117905889963179</id><published>2009-06-24T20:19:00.001+03:00</published><updated>2009-09-02T22:52:13.599+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='openmp'/><category scheme='http://www.blogger.com/atom/ns#' term='study'/><category scheme='http://www.blogger.com/atom/ns#' term='parallel programming'/><category scheme='http://www.blogger.com/atom/ns#' term='latex'/><category scheme='http://www.blogger.com/atom/ns#' term='tbb'/><category scheme='http://www.blogger.com/atom/ns#' term='life'/><category scheme='http://www.blogger.com/atom/ns#' term='qt'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Just for fun</title><content type='html'>Первый год обучения в университете получился очень интересным и необычным. Во-первых, я безумно рад что выбрал именно ХНУРЭ, а не НАУ или ДонНТУ. Почему? Потому что только у нас есть такие интересные вещи как &lt;a href="http://kiu.kture.kharkov.ua/rus/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%9A%D1%83%D1%80%D1%81%D1%8B_%D0%BA%D0%B0%D1%84%D0%B5%D0%B4%D1%80%D1%8B_%D0%90%D0%9F%D0%92%D0%A2"&gt;CET&lt;/a&gt; и такие люди как: &lt;a href="http://zoresvit.blogspot.com/"&gt;Zoresvit&lt;/a&gt;, &lt;a href="http://draft.blogger.com/post-edit.g?blogID=1835049761574940534&amp;amp;postID=7871117905889963179" com=""&gt;Владимир Обризан&lt;/a&gt;, &lt;a href="http://davydovm.blogspot.com/"&gt;Макс Давыдов&lt;/a&gt;, &lt;b&gt;Сергей Зайченко&lt;/b&gt;, &lt;b&gt;Александр Адамов&lt;/b&gt; и многие-многие другие. Общаться с ними очень интересно, а гланое - полезно. А курсы &lt;b&gt;CET&lt;/b&gt;  - прогрессивная модель получения высшего образования.&lt;br /&gt;&lt;br /&gt;Я хотел выделить наиболее интересные вещи, с которыми столкнулся в этом году:&lt;br /&gt;1. &lt;b&gt;С++&lt;/b&gt;. Да, я раньше изучал &lt;b&gt;С&lt;/b&gt;, но это совершенно другой язык, чтобы там не говорили =). По правде говоря, мне долгое время больше нравился именно &lt;b&gt;С&lt;/b&gt;, пока не начались курсы &lt;b&gt;Зайченко&lt;/b&gt;, на которых он показал нам истинную красоту &lt;b&gt;С++&lt;/b&gt; =)&lt;br /&gt;2.  &lt;b&gt;Parallel Programming: &lt;a href="http://openmp.org/wp/"&gt;OpenMP&lt;/a&gt;,&lt;a href="https://computing.llnl.gov/tutorials/pthreads/"&gt;PThreads&lt;/a&gt;, &lt;a href="http://www.threadingbuildingblocks.org/"&gt;TBB&lt;/a&gt;&lt;/b&gt;. В век многоядерных процессоров без этого никуда. Спасибо &lt;a href="http://obrizan.blogspot.com/"&gt;Владимиру Обризану&lt;/a&gt; за его курс по &lt;a href="http://kiu.kture.kharkov.ua/rus/%D0%9C%D0%BD%D0%BE%D0%B3%D0%BE%D1%8F%D0%B4%D0%B5%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5"&gt;многоядерному программированию&lt;/a&gt; и &lt;a href="http://kiu.kture.kharkov.ua/rus/%D0%92%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B2_%D0%BE%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8E_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D0%9F%D0%9E"&gt;оптимизации ПО&lt;/a&gt;!&lt;br /&gt;3. &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;. Я рекомендую обратить ваше внимание на этот интересный язык программирования, позволяющий решать определённые задачи действительно просто и красиво. В Интернете доступна хорошая книга по &lt;b&gt;Python&lt;/b&gt; для программистов на других языках - &lt;a href="http://diveintopython.org/"&gt;Dive into Python&lt;/a&gt;.&lt;br /&gt;4. &lt;a href="http://www.latex-project.org/"&gt;LaTeX&lt;/a&gt; - система подготовки документов. О &lt;b&gt;LaTeX&lt;/b&gt; можно почитать &lt;a href="http://korkholeh.blogspot.com/2008/05/latex.html"&gt;здесь&lt;/a&gt;. Есть учебный курс &lt;a href="http://www.intuit.ru/department/publish/latex/"&gt;здесь&lt;/a&gt;.&lt;br /&gt;5. &lt;a href="http://www.qtsoftware.com/products/"&gt;QT&lt;/a&gt; - воопреки существующим заблуждениям, &lt;b&gt;QT&lt;/b&gt; - это не только библиотека для &lt;b&gt;GUI&lt;/b&gt;, но и мощный фреймворк для создания пользовательских приложений.&lt;br /&gt;&lt;br /&gt;Заканчивается сессия и наконец-то появится время для их изучения =).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1835049761574940534-7871117905889963179?l=www.amd4ever.org.ua' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.amd4ever.org.ua/feeds/7871117905889963179/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1835049761574940534&amp;postID=7871117905889963179' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/7871117905889963179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1835049761574940534/posts/default/7871117905889963179'/><link rel='alternate' type='text/html' href='http://www.amd4ever.org.ua/2009/06/just-for-fun.html' title='Just for fun'/><author><name>amd4ever</name><uri>http://www.blogger.com/profile/13958191077941383321</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_RNMrG3uqd7I/STtz80tNKjI/AAAAAAAAAAM/R6z0q4PnIwk/S220/phoenix_color-small.gif'/></author><thr:total>0</thr:total></entry></feed>
