<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Web development and stuff</title>
	<atom:link href="http://sapper4ever.net/stillwaiting/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://sapper4ever.net/stillwaiting</link>
	<description></description>
	<lastBuildDate>Mon, 24 May 2010 07:03:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>InstallShield MSI script project: pass data to Setup.Rul from command line</title>
		<link>http://sapper4ever.net/stillwaiting/?p=76</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=76#comments</comments>
		<pubDate>Mon, 24 May 2010 07:03:09 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[InstallSheld scripting]]></category>
		<category><![CDATA[cmdline]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[InstallShield]]></category>
		<category><![CDATA[setup.rul]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=76</guid>
		<description><![CDATA[You can easily pass data from the command line to Setup.Rul by passing /z parameter to command line:
setup.exe /z"MYDATA"
This sets the CMDLINE variable:

function OnFirstUiBefore()
begin
    MessageBox(CMDLINE, MB_OK);
end;

]]></description>
			<content:encoded><![CDATA[<p>You can easily pass data from the command line to Setup.Rul by passing /z parameter to command line:</p>
<pre>setup.exe /z"MYDATA"</pre>
<p>This sets the CMDLINE variable:</p>
<pre>
function OnFirstUiBefore()
begin
    MessageBox(CMDLINE, MB_OK);
end;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=76</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>py2exe: win32con missing module</title>
		<link>http://sapper4ever.net/stillwaiting/?p=70</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=70#comments</comments>
		<pubDate>Tue, 16 Feb 2010 06:54:42 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[missing modules]]></category>
		<category><![CDATA[py2exe]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=70</guid>
		<description><![CDATA[Hi everybody,
Yesterday I tried to turn my python code into win32 executable with py2exe utility and faced with problem: py2exe was unable to find win32con module with error:
The following modules appear to be missing ['win32con']
In a couple of hours I googled next solution: one should simply install Python for Windows extensions. This fixed everything.
]]></description>
			<content:encoded><![CDATA[<p>Hi everybody,</p>
<p>Yesterday I tried to turn my <a href="http://python.org">python</a> code into win32 executable with <a href="http://py2exe.org">py2exe</a> utility and faced with problem: py2exe was unable to find win32con module with error:</p>
<blockquote><p>The following modules appear to be missing ['win32con']</p></blockquote>
<p>In a couple of hours I googled next solution: one should simply install <a href="http://sourceforge.net/projects/pywin32/">Python for Windows extensions</a>. This fixed everything.</p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=70</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiling nagios plugins with cygwin: handling ./configure problem with ICMP</title>
		<link>http://sapper4ever.net/stillwaiting/?p=67</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=67#comments</comments>
		<pubDate>Wed, 24 Jun 2009 09:48:48 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[cygwin]]></category>
		<category><![CDATA[configure]]></category>
		<category><![CDATA[icmp]]></category>
		<category><![CDATA[nagios plugin]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=67</guid>
		<description><![CDATA[To build nagios plugins in windows, one should start cygwin and execute ./configure and make commands. While doing this, I faced with problem: ./configure script just hangs on the &#8220;checking for ICMP ping syntax&#8221; line.
Since I needed only one plugin (check_http) and I&#8217;m not familiar with icmp, cygwin and bash, I simply removed lines from [...]]]></description>
			<content:encoded><![CDATA[<p>To build nagios plugins in windows, one should start cygwin and execute <em>./configure</em> and <em>make </em>commands. While doing this, I faced with problem: <em>./configure</em> script just hangs on the <em>&#8220;checking for ICMP ping syntax&#8221;</em> line.</p>
<p>Since I needed only one plugin (check_http) and I&#8217;m not familiar with icmp, cygwin and bash, I simply removed lines from <em>./configure</em>:</p>
<pre>{ echo "$as_me:$LINENO: checking for ICMP ping syntax" &gt;&amp;5
echo $ECHO_N "checking for ICMP ping syntax... $ECHO_C" &gt;&amp;6; }
ac_cv_ping_packets_first=no
ac_cv_ping_has_timeout=no
[REMOVE_THIS]
if test -n "$with_ping_command"
then
    { echo "$as_me:$LINENO: result: (command-line) $with_ping_command" &gt;&amp;5
.....
.....
echo "${ECHO_T}$with_ping_command" &gt;&amp;6; }

else
    { echo "$as_me:$LINENO: WARNING: unable to find usable ping syntax" &gt;&amp;5
echo "$as_me: WARNING: unable to find usable ping syntax" &gt;&amp;2;}
fi
[/REMOVE_THIS]

cat &gt;&gt;confdefs.h &lt;&lt;_ACEOF
#define PING_COMMAND "$with_ping_command"
_ACEOF</pre>
<p>After this <em>./configure </em>finished it&#8217;s work. Then I called <em>make</em>, it built 23 plugins before thew the error and died. Luckily create_http.exe was created.</p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=67</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>QtWebKit &#8211; turn javascript and images off</title>
		<link>http://sapper4ever.net/stillwaiting/?p=65</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=65#comments</comments>
		<pubDate>Thu, 18 Jun 2009 08:35:01 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[C++/Qt]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[disable images]]></category>
		<category><![CDATA[QtWebKit]]></category>
		<category><![CDATA[QWebView]]></category>
		<category><![CDATA[turn off javascript]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=65</guid>
		<description><![CDATA[How to turn javascript and images off in QWebView?
QWebView *myWebView = new QWebView(this);
....
myWebView-&#62;settings()-&#62;setAttribute(QWebSettings::JavascriptEnabled, false);
myWebView-&#62;settings()-&#62;setAttribute(QWebSettings::AutoLoadImages, false);
That&#8217;s all  
]]></description>
			<content:encoded><![CDATA[<p>How to turn javascript and images off in QWebView?</p>
<pre>QWebView *myWebView = new QWebView(this);
....
myWebView-&gt;settings()-&gt;setAttribute(QWebSettings::JavascriptEnabled, false);
myWebView-&gt;settings()-&gt;setAttribute(QWebSettings::AutoLoadImages, false);</pre>
<p>That&#8217;s all <img src='http://sapper4ever.net/stillwaiting/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=65</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>QWhatsThis &#8211; fighting with wordwrap</title>
		<link>http://sapper4ever.net/stillwaiting/?p=62</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=62#comments</comments>
		<pubDate>Sat, 13 Jun 2009 10:01:42 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[C++/Qt]]></category>
		<category><![CDATA[nobr]]></category>
		<category><![CDATA[problem]]></category>
		<category><![CDATA[qt]]></category>
		<category><![CDATA[QWhatsThis]]></category>
		<category><![CDATA[wordwrap]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=62</guid>
		<description><![CDATA[Another problem with QWhatsThis::showText() method: word wrapping. If you want to turn it off, you&#8217;d probably face with some problems: it&#8217;s not as easy as it supposed to be.
I&#8217;ve found the solution that satisfied me: instead of calling
QWhatsThis::showText(myPoint, "blah blah...", ...);
I frame &#8220;blah blah &#8230;&#8221; text into table with &#60;nobr&#62; tags and use this call:
QWhatsThis::showText(myPoint, [...]]]></description>
			<content:encoded><![CDATA[<p>Another problem with QWhatsThis::showText() method: word wrapping. If you want to turn it off, you&#8217;d probably face with some problems: it&#8217;s not as easy as it supposed to be.</p>
<p>I&#8217;ve found the solution that satisfied me: instead of calling</p>
<pre>QWhatsThis::showText(myPoint, "blah blah...", ...);</pre>
<p>I frame &#8220;blah blah &#8230;&#8221; text into table with &lt;nobr&gt; tags and use this call:</p>
<pre>QWhatsThis::showText(myPoint, "&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;nobr&gt;blah blah...&lt;/nobr&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;", ...);</pre>
<p>This solved my problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=62</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ProtectMy.Info &#8211; leave spam no chance</title>
		<link>http://sapper4ever.net/stillwaiting/?p=60</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=60#comments</comments>
		<pubDate>Sat, 13 Jun 2009 09:52:23 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[spam]]></category>
		<category><![CDATA[no spam]]></category>
		<category><![CDATA[protectmy.info]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=60</guid>
		<description><![CDATA[Today I&#8217;ve met protectmy.info &#8211; free service that allows anyone to publish his contacts (like e-mail) without fair to be spammed.
It&#8217;s principle is easy: before showing e-mail one asked to enter CAPTCHA (hard-to-read words from image). If one succeed he can read the e-mail. Spambots are too stupid to pass this check, so e-mail becomes [...]]]></description>
			<content:encoded><![CDATA[<p>Today I&#8217;ve met <a href="http://protectmy.info">protectmy.info</a> &#8211; free service that allows anyone to publish his contacts (like e-mail) without fair to be spammed.</p>
<p>It&#8217;s principle is easy: before showing e-mail one asked to enter CAPTCHA (hard-to-read words from image). If one succeed he can read the e-mail. Spambots are too stupid to pass this check, so e-mail becomes protected for sure.</p>
<p>And now I can publish my <a href="http://protectmy.info?page=v7xtxmyfcg" target="_new">e-mail</a>. Yes! The sweet Victory!</p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=60</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qt: QWhatsThis &#8211; handling  clicks</title>
		<link>http://sapper4ever.net/stillwaiting/?p=54</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=54#comments</comments>
		<pubDate>Sat, 13 Jun 2009 09:37:34 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[C++/Qt]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[Add new tag]]></category>
		<category><![CDATA[handling url clicks]]></category>
		<category><![CDATA[qt]]></category>
		<category><![CDATA[QWhatsThis]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=54</guid>
		<description><![CDATA[QWhatsThis::showText() shows beautiful hint where one can place HTML formatted text. The question is: how we can handle link clicks, like &#60;a href=&#8221;more&#8221;&#62;more&#8230;&#60;/a&#62;?
The answer is located in this thread: one should re-implement QWidget::event() method for &#8220;parent&#8221; widget (3rd param in QWhatsThis::showText() method), like:
void MyWidget::event(QEvent *_event)
{
    if (_event-&#62;type() == QEvent::WhatsThisClicked){
    [...]]]></description>
			<content:encoded><![CDATA[<p>QWhatsThis::showText() shows beautiful hint where one can place HTML formatted text. The question is: how we can handle link clicks, like &lt;a href=&#8221;more&#8221;&gt;more&#8230;&lt;/a&gt;?</p>
<p>The answer is located in this <a href="http://www.qtcentre.org/forum/archive/index.php/t-7394.html">thread</a>: one should re-implement QWidget::event() method for &#8220;parent&#8221; widget (3rd param in QWhatsThis::showText() method), like:</p>
<pre>void MyWidget::event(QEvent *_event)
{
    if (_event-&gt;type() == QEvent::WhatsThisClicked){
        if (QWhatsThisClickedEvent* clicked = dynamic_cast(_event)){
            QString href = clicked-&gt;url(); // here is the "href" value of the link user clicked
            ...........
        }
    }
    return QWidget::event(_event);
}</pre>
<p>So, when user clicks on the &lt;a href&gt; link, MyWidget::event() fires, extracts the &#8220;url&#8221; and handles it.</p>
<p>If you don&#8217;t want to re-implement the QWidget::event() method, you could use installEventFilter().</p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=54</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Сапер: какова вероятность того, что поле откроется?</title>
		<link>http://sapper4ever.net/stillwaiting/?p=43</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=43#comments</comments>
		<pubDate>Sun, 14 Dec 2008 17:03:15 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[игра сапер]]></category>
		<category><![CDATA[наука - lite]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[python sapper helper]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=43</guid>
		<description><![CDATA[Кто играл в &#8220;сапера&#8221;, тот знает, что бывают ситуации, когда логически вычислить положение следующей мины/пустой клетки невозможно. Я задался вопросом: &#8220;А какова вообще вероятность того, что поле откроется, если открывать его настолько аккуратно, насколько это возможно (исключить человеческий фактор)?&#8221; Очевидно, что такая цифра существует. Собственно эта статья посвящается тому, как мне удалось приблизиться к этим [...]]]></description>
			<content:encoded><![CDATA[<p>Кто играл в &#8220;сапера&#8221;, тот знает, что бывают ситуации, когда логически вычислить положение следующей мины/пустой клетки невозможно. Я задался вопросом: &#8220;<strong>А какова вообще вероятность того, что поле откроется, если открывать его настолько аккуратно, насколько это возможно (исключить человеческий фактор)?</strong>&#8221; Очевидно, что такая цифра существует. Собственно эта статья посвящается тому, как мне удалось приблизиться к этим числам. Сначала сразу приведу результаты, чтобы не напрягать лишний раз людей, которые зашли сюда только за ними <img src='http://sapper4ever.net/stillwaiting/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Результаты:</strong></p>
<p>Сразу скажу, что эти числа получены в ходе экспериментов и научную ценность могут представлять только после теоретического основания, если кто-нибудь когда-нибудь решит его сделать; кроме того возможны погрешности. Это всего лишь попытка найти их. Тем не менее:</p>
<p>Новичок (поле 8&#215;8, 10 мин), первый клик в углу: вероятность 75%;</p>
<p>Новичок, первый клик в центре: вероятность 67.7%.</p>
<p>Любитель (поле 16&#215;16, 40 мин), первый клик в углу: вероятность 66.1%</p>
<p>Любитель, первый клик в центре: вероятность 62.9%</p>
<p>Профессионал (30&#215;16, 99 мин), первый клик в углу: 23.1%</p>
<p>Профессионал, первый клик в центре: 22.9%</p>
<p><strong>Как результаты были получены:</strong></p>
<p>Как я уже писал, результаты экспериментальные. Поскольку постановка звучала так: &#8220;Какова вероятность того, что самый аккуратный/лучший/идеальный игрок в мире откроет поле размером NxM с K минами, если на первом клике подорваться невозможно&#8221;, то для начала был сделан алгоритм, который достаточно хорошо (близок к идеальному) открывает данное ему поле. После этого, для каждого вида поля я создавал 10000 досок и давал ему их решать. Число успешно открытых им досок деленное на 100 и бралось в качестве претендента для искомой вероятности.</p>
<p><strong>Описание &#8220;близкого к идеальному&#8221; алгоритму, который использовался в эксперименте:</strong></p>
<p>Алгоритм итерационный:</p>
<p>- Если на i-м шаге можно со 100% уверенностью определить, что в какой-то ячейке есть мина, то алгоритм помечает ее как мину. Пример ситуации: вокруг единички все ячейки открыты, одна закрытая. Значит там мина:)</p>
<p>- Если на i-м шаге можно со 100% уверенностью определить, что какая-то ячейка пустая, то алгоритм &#8220;кликает&#8221; на нее. Пример: единичка, возле нее установлена &#8220;мина&#8221;. Значит алгоритм кликает на все оставшиеся соседние с этой единичкой ячейки.</p>
<p>- Если на i-м шаге нельзя со 100% уверенностью определить, где мина есть, а где ее нет, то алгоритм 50 раз случайным образом расставляет оставшиеся мины так, чтобы ситуация на доске была допустимой. То есть он не будет возле открытой единички ставить 3 мины. После этого он анализирует эти 50 возможных расстановок, находит клетки, где мины встречались часто, где редко (среди этих 50-и расстановок), то есть находит клетки, в которых наибольшая вероятность мины (или ее отсутствия), и ставит туда мину (или кликает).</p>
<p>Как видно, алгоритм имитирует человека, который играет &#8220;нечестно&#8221;: использует программу, которая на каждом шаге вычисляет для него вероятность того, где мины есть, а где их нет. Если он не идеален, то ИМХО весьма хорош:)</p>
<p><strong>Зависимость вероятности успеха (открыть поле) от плотности мин:</strong></p>
<p>Для поля размером 8&#215;8 я посчитал вероятности для любого количества мин (те успех когда на поле 0 мин, 1 мина, 2 мины, &#8230; 62 мины). Вот как для этого поля выглядит график зависимости вероятность успеха от плотности мин:<br />
<img src="http://sapper4ever.net/stillwaiting/images/sapper_probability.jpg" alt="" /></p>
<p><strong>Выводы:</strong></p>
<p>Кроме полученных чисел можно заметить, что вероятность так же зависит от начального клика, лучше начинать открывать с угла:)</p>
<p>Еще есть такой ресурс sweepmines.com, на котором предлагают открыть поле 8&#215;8, 12 мин, в случае успеха возвращают удваивоенную ставку. Так вот, вероятность открыть такое поле &#8212; 57% (если с угла). Так что в принципе можете попытаться &#8220;обмануть&#8221; ресурс и заработать бабла. Но я бы не рискнул <img src='http://sapper4ever.net/stillwaiting/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Приложения:</strong></p>
<p><a href="http://sapper4ever.net/stillwaiting/sapper_results.html">численные результаты экспериментов (для всех плотностей мин на новичке, до 44 мин на любителе, немного на профи)</a>;</p>
<p><a href="http://sapper4ever.net/stillwaiting/sapper_solver.tar.gz">исходники алгоритма (на питоне), который использовался для эксперимента</a>;</p>
<p><a href="http://sapper4ever.net/stillwaiting/sapperPyHelper.tar.gz">программа, которая помогает &#8220;открывать&#8221; поле простому игроку, показывая вероятности нахождения/отсутствия мины (питон + pyWidgets).</a> Надеюсь Rogen не обидится (очень пригодится тем, кто участвует в рейтинге &#8220;по плотности мин&#8221; на <a href="http://minesweeper.ru">minesweeper.ru</a> <img src='http://sapper4ever.net/stillwaiting/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=43</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATnotes &#8211; свободные стикеры (записки) для рабочего стола Windows XP</title>
		<link>http://sapper4ever.net/stillwaiting/?p=41</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=41#comments</comments>
		<pubDate>Fri, 12 Dec 2008 05:16:05 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[soft]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[ATnotes]]></category>
		<category><![CDATA[бесплатные стикеры]]></category>
		<category><![CDATA[рабочий стол]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=41</guid>
		<description><![CDATA[Стикеры &#8211; наклейки-записки для рабочего стола. Можно туда записать список своих дел на день, и он будет висеть у вас перед глазами, постоянно напоминая о себе. Очень удобно.
Для Windows XP существует огромное множество таких программ: Power Notes, Post-It Notes, Digital Desktop Stickers, и даже MoRUN.net Sticker Professional Edition    итд. Как правило, это [...]]]></description>
			<content:encoded><![CDATA[<p>Стикеры &#8211; наклейки-записки для рабочего стола. Можно туда записать список своих дел на день, и он будет висеть у вас перед глазами, постоянно напоминая о себе. Очень удобно.</p>
<p>Для Windows XP существует огромное множество таких программ: <a href="www.pw-soft.com">Power Notes</a>, <a href="http://www.3m.com/us/office/postit/digital/digital_notes.html">Post-It Notes</a>, <a href="http://desktop-tools.net/digital-desktop-stickers.html">Digital Desktop Stickers</a>, и даже <a href="http://www.morun.net/">MoRUN.net Sticker Professional Edition</a> <img src='http://sapper4ever.net/stillwaiting/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   <a href="http://www.filetransit.com/files.php?name=Desktop_Notes-3-1">итд</a>. Как правило, это платные продукты, цена колеблется от $10 до $20.</p>
<p>Но существуют и бесплатные аналоги, которые ничем не уступают вышеперечисленным. Например <a href="http://atnotes.free.fr/">ATnotes</a>. К сожалению, разработка и поддержка продукта закончилась, тем не менее это очень стабильный и достойный представитель стикерского софта. Скачивается с <a href="http://atnotes.free.fr/">официального сайта</a>, ставится в три клика, запускается при загрузке, интуитивно понятный интерфейс, редактирование шрифта/фона, возможность делать их полупрозрачными поверх всех окон, поддержка кириллицы и прочие вкусности. Рекомендую всем.</p>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=41</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ссылающиеся друг на друга объекты в питоне: возможные последствия</title>
		<link>http://sapper4ever.net/stillwaiting/?p=24</link>
		<comments>http://sapper4ever.net/stillwaiting/?p=24#comments</comments>
		<pubDate>Sun, 07 Dec 2008 16:43:56 +0000</pubDate>
		<dc:creator>stillwaiting</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[destructor doesn't fire]]></category>
		<category><![CDATA[деструктор не срабатывает]]></category>
		<category><![CDATA[питон]]></category>

		<guid isPermaLink="false">http://sapper4ever.net/stillwaiting/?p=24</guid>
		<description><![CDATA[В питоне объект уничтожается (и вызывается его деструктор) только тогда, когда на него ничего не ссылается. Что делать, когда объект A ссылается на объект B, а объект B в свою очередь ссылается на объект A? В этом случае деструкторы этих объектов никогда не будут вызваны. В частности, этот код
import sys
print(sys.version)

class C(object):
    def [...]]]></description>
			<content:encoded><![CDATA[<p>В питоне объект уничтожается (и вызывается его деструктор) только тогда, когда на него ничего не ссылается. Что делать, когда объект A ссылается на объект B, а объект B в свою очередь ссылается на объект A? В этом случае деструкторы этих объектов никогда не будут вызваны. В частности, этот код</p>
<pre>import sys
print(sys.version)

class C(object):
    def __del__(self):
        print("Die C!")

class D(object):
    def __del__(self):
        print("Die D!")

c = C()
d = D()</pre>
<p>выведет<br />
<code><br />
2.5.2 (r252:60911, Apr 21 2008, 11:12:42)<br />
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]<br />
Die C!<br />
Die D!<br />
</code>,<br />
но если мы вконец допишем</p>
<pre>c.d = d
d.c = c</pre>
<p>и запустим, то получим</p>
<p><code><br />
2.5.2 (r252:60911, Apr 21 2008, 11:12:42)<br />
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]<br />
</code>.<br />
Все вышенаписанное справедливо как для 2.x ветки, так и для python 3000.</p>
<p>Казалось бы, какой пустяк. Тем не менее, это может вызывать непредсказуемое поведение в, казалось бы, простейших ситуациях. Рассмотрим один пример:</p>
<p>Наверое самый известный ОО паттерн: синглтон. Давайте реализуем его на питоне:</p>
<pre>import sys

print(sys.version)

class Singleton(object):
	instance = None
	def __new__(type, *args, **kwargs):
		if type.instance == None:
			type.instance = object.__new__(type, *args, **kwargs)
		return type.instance

class A(Singleton):
       def __del__(self):
		print ("A's destructor is called!")

aobj = A()
bobj = A()

print str(aobj)
print str(bobj)</pre>
<p>, результат будет:</p>
<pre>2.5.2 (r252:60911, Apr 21 2008, 11:12:42)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
&lt;__main__.A object at 0xb7d8a04c&gt;
&lt;__main__.A object at 0xb7d8a04c&gt;</pre>
<p>aobj и bobj указывают на один и тот же объект, но в конце работы программы деструктор для него не вызывается. Возникает естественный вопрос: &#8220;Почему&#8221;?</p>
<p>В питоне тип (класс) &#8211; тоже объект, чем мы и воспользовались для реализации синглтона: когда мы первый раз создали объект класса A, мы присвоили свойству instance класса(-объекта) A ссылку на этот объект. Все логично, но мы забыли об одной вещи: у объекта aobj есть свойство __class__, которое указывает на класс объекта. В нашем случае это класс A.</p>
<p>То есть получается следующее: aobj.__class__ указывает на A, а A.instance указывает на aobj, ссылающиеся друг на друга объекты a и A, их деструкторы никогда не будут вызываны.</p>
<p>Добьем наш пример:</p>
<pre>import sys

print(sys.version)

class Singleton(object):
	instance = None
	def __new__(type, *args, **kwargs):
		if type.instance == None:
			type.instance = object.__new__(type, *args, **kwargs)
			Singleton_Destructor.types.append(type)
		return type.instance

class Singleton_Destructor:
	types = []
	def __del__(self):
		for i in self.__class__.types:
			del i.instance

sd = Singleton_Destructor()

class A(Singleton):
	def __del__(self):
		print ("A's destructor is called!")

a = A()
b = A()

print(str(a))
print(str(b))</pre>
<p>вернет долгожданный</p>
<pre>[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
&lt;__main__.A object at 0xb7bb430c&gt;
&lt;__main__.A object at 0xb7bb430c&gt;
A's destructor is called!</pre>
]]></content:encoded>
			<wfw:commentRss>http://sapper4ever.net/stillwaiting/?feed=rss2&amp;p=24</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
