<?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>warczakowski.pl</title>
	<atom:link href="http://warczakowski.pl/feed/" rel="self" type="application/rss+xml" />
	<link>http://warczakowski.pl</link>
	<description>Littera scripta manet</description>
	<lastBuildDate>Mon, 17 Oct 2011 14:31:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Django pod Nginx w pięć minut</title>
		<link>http://warczakowski.pl/2011/09/django-pod-nginx-w-piec-minut/</link>
		<comments>http://warczakowski.pl/2011/09/django-pod-nginx-w-piec-minut/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 15:06:27 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Systemy operacyjne]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=347</guid>
		<description><![CDATA[Zgodnie z dokumentacją do Nginx uruchomienie aplikacji Django sprowadza się do wpisania odpowiedniej konfiguracji do pliku nginx.conf, zrestartowaniu serwera i wystartowaniu aplikacji w trybie FastCGI. Wykonanie tych czynności nie powinno zająć więcej niż pięć minut. Sprawdzimy to na przykładzie FreeBSD. Załóżmy, że aplikacja zainstalowana jest w katalogu /usr/local/www/aplikacja/ i nasłuchiwać będzie na porcie 8080, a [...]]]></description>
			<content:encoded><![CDATA[<p>Zgodnie z <a href=http://wiki.nginx.org/DjangoFastCGI>dokumentacją do Nginx</a> uruchomienie aplikacji Django sprowadza się do wpisania odpowiedniej konfiguracji do pliku <em>nginx.conf</em>, zrestartowaniu serwera i wystartowaniu aplikacji w trybie FastCGI. Wykonanie tych czynności nie powinno zająć więcej niż pięć minut. Sprawdzimy to na przykładzie FreeBSD.</p>
<p><span id="more-347"></span></p>
<p>Załóżmy, że aplikacja zainstalowana jest w katalogu <em>/usr/local/www/aplikacja/</em> i nasłuchiwać będzie na porcie 8080, a serwer na standardowym porcie 80. Wtedy do pliku <em>/usr/local/etc/nginx/nginx.conf</em> w sekcji <em>http</em> wpisujemy:</p>
<pre>
server {
    listen 80;
    server_name localhost;

    location /media {
        root /usr/local/www/aplikacja/;
    }

    location / {
        fastcgi_pass 127.0.0.1:8080;
        fastcgi_param SERVER_ADDR $server_addr;
        fastcgi_param SERVER_NAME $server_name;
        fastcgi_param SERVER_PORT $server_port;
        fastcgi_param SERVER_PROTOCOL $server_protocol;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;
    }
}
</pre>
<p>Teraz wystarczy zrestartować Nginx i uruchomić aplikację:</p>
<pre>
python manage.py runfcgi host=127.0.0.1 port=8080 --settings=settings
</pre>
<p>I to wszystko. Chyba zmieściliśmy się w pięciu minutach.</p>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2011/09/django-pod-nginx-w-piec-minut/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django i Apache pod Windows XP</title>
		<link>http://warczakowski.pl/2011/09/django-i-apache-pod-windows-xp/</link>
		<comments>http://warczakowski.pl/2011/09/django-i-apache-pod-windows-xp/#comments</comments>
		<pubDate>Sun, 11 Sep 2011 13:22:19 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Systemy operacyjne]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[ms windows]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=301</guid>
		<description><![CDATA[Ostatnio przyszło mi wdrażać aplikację w Django na desktopie z zainstalowanym Windows XP. Desktop miał służyć jako serwer dla aplikacji, z której korzystałaby osoba pracująca na desktopie oraz inne osoby w sieci. Bazą danych miał być PostgreSQL a serwerem WWW nginx, który uruchamia aplikację Django poprzez FastCGI. Ponieważ Django do pracy jako FastCGI wymaga zainstalowanego [...]]]></description>
			<content:encoded><![CDATA[<p>Ostatnio przyszło mi wdrażać aplikację w Django na desktopie z zainstalowanym Windows XP. Desktop miał służyć jako serwer dla aplikacji, z której korzystałaby osoba pracująca na desktopie oraz inne osoby w sieci. Bazą danych miał być PostgreSQL a serwerem WWW <em>nginx</em>, który uruchamia aplikację Django poprzez FastCGI. Ponieważ Django do pracy jako FastCGI wymaga zainstalowanego pakietu <em>flup</em>, a ten pracuje tylko w środowiskach uniksopodobnych, powstał problem. Rozwiązaniem było zainstalowanie serwera Apache z modułem <em>mod_wsgi</em>. Opis instalacji znajduje się dalej. Został sprawdzony pod Windows XP, Windows 7 oraz Windows Server 2008.</p>
<p><span id="more-301"></span></p>
<h3>Pakiety wykorzystane w instalacji</h3>
<ul>
<li><a href=http://python.org/ftp/python/2.7.2/python-2.7.2.msi>Python 2.7.2</a></li>
<li><a href=http://www.djangoproject.com/download/1.2.7/tarball&#47>Django 1.2.7</a></li>
<li><a href=http://www.stickpeople.com/projects/python/win-psycopg/psycopg2-2.4.2.win32-py2.7-pg9.0.4-release.exe>Psycopg2 2.4.2</a></li>
<li><a href=http://www.enterprisedb.com/products-services-training/pgdownload#windows>PostgreSQL 9.0.4</a></li>
<li><a href=http://apache.privatejetscharter.net//httpd/binaries/win32/httpd-2.2.20-win32-x86-no_ssl.msi>Apache 2.2.20</a></li>
<li><a href=http://code.google.com/p/modwsgi/downloads/detail?name=mod_wsgi-win32-ap22py27-3.3.so>mod_wsgi-3.3</a></li>
</ul>
<h3>Opis instalacji</h3>
<p>Przed przystąpieniem do instalacji musimy wiedzieć, że Apache Software Foundation nie dostarcza 64 bitowych binarek swojego serwera. Jeśli chcemy mieć wersję 64 bitową musimy sobie ją sami skompilować bądź znaleźć w sieci gotowe, nieoficjalne 64 bitowe binaria. Jeśli zainstalujemy oficjalną, 32 bitową wersję serwera, Python oraz psycopg2 również muszą być 32 bitowe.</p>
<p>Po zainstalowaniu pakietów Python, Django i psycopg2 instalujemy PostgreSQL, po czym uruchamiamy pgAdmin i zakładamy bazę danych dla wdrażanej aplikacji Django, a następnie w katalogu wspomnianej aplikacji wstukujemy polecenie:</p>
<pre>python manage.py syncdb</pre>
<p>Jeżeli okaże się, że system nie widzi polecenia <em>python</em> należy do zmiennej środowiskowej <em>PATH</em> dopisać katalog z zainstalowanym Pythonem. W naszym przypadku jest to C:\Python27. Jeśli poprzednie polecenie wykonało się prawidłowo możemy sprawdzić działanie naszej aplikacji uruchamiając ją przy pomocy testowego serwera WWW:</p>
<pre>python manage.py runserver</pre>
<p>Aplikacja powinna działać pod adresem http://127.0.0.1:8008/. Jeśli wszystko jest w porządku wyłączamy serwer testowy i przechodzimy do instalacji serwera Apache. W trakcie instalacji instalator zapyta nas o nazwę serwera, domenę i email administratora. Wystarczy podać <em>localhost</em> w przypadku serwera i domeny oraz <em>root@localhost</em> w przypadku adresu email.</p>
<p>Po zainstalowaniu serwera Apache należy przekopiować moduł <em>mod_wsgi-win32-ap22py27-3.3.so</em> do odpowiedniej lokalizacji. W naszym przypadku jest to:</p>
<pre>C:\Program Files\Apache Software Foundation\Apache2.2\modules</pre>
<p>i zmienić nazwę na <em>mod_wsgi</em>.</p>
<p>W tym momencie mamy wszystko przygotowane do uruchomienia aplikacji przez serwer Apache. Teraz musimy stworzyć plik <em>django.wsgi</em> i umieścić go w naszej aplikacji oraz odpowiednio zmodyfikowac plik konfiguracyjny serwera Apache <em>httpd.conf</em>. Załóżmy, że nasza aplikacja znajduje się w katalogu:</p>
<pre>C:\Projekty\mojprojekt\</pre>
<p>Umieszczamy w tym katalogu plik <em>django.wsgi</em> o treści:</p>
<pre>
import os, sys

sys.path.append('C:\\Projekty')
sys.path.append('C:\\Projekty\\mojprojekt')
os.environ['DJANGO_SETTINGS_MODULE'] = 'mojprojekt.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>Następnie modyfikujemy plik <em>httpd.conf</em> znajdujący się, w naszym przypadku, w katalogu:</p>
<pre>C:\Program Files\Apache Software Foundation\Apache2.2\conf</pre>
<p>dopisując do niego:</p>
<pre>
LoadModule wsgi_module modules/mod_wsgi.so

Alias /media/ "C:/Projekty/mojprojekt/media/"

&lt;Directory C:/Projekty/mojprojekt&gt;
  Order deny,allow
  Allow from all
&lt;/Directory&gt;

WSGIScriptAlias / "C:/Projekty/mojprojekt/django.wsgi"
</pre>
<p>Jeśli wszystko zrobiliśmy dobrze możemy zrestartować serwer Apache i cieszyć się działającą aplikacją Django. Ponieważ PostgreSQL i Apache instalują się jako usługi, po restarcie komputera użytkownik nie musi wykonywać żadnych dodatkowych czynności &#8211; wystarczy, że wpisze w swojej przeglądarce adres <em>http://127.0.0.1</em> i może korzystać z aplikacji.</p>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2011/09/django-i-apache-pod-windows-xp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Identyfikatory i klasy w CSS a JavaScript</title>
		<link>http://warczakowski.pl/2011/05/identyfikatory-i-klasy-w-css-a-javascript/</link>
		<comments>http://warczakowski.pl/2011/05/identyfikatory-i-klasy-w-css-a-javascript/#comments</comments>
		<pubDate>Wed, 25 May 2011 20:40:31 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Tworzenie stron WWW]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=244</guid>
		<description><![CDATA[Element w HTML może zawierać atrybut id nadający mu unikatowy identyfikator. Dzięki temu możliwe jest napisanie reguł CSS odnoszących się bezpośrednio do tego elementu z pominięciem hierarchii dokumentu. Atrybut class umożliwia napisanie reguł CSS dla grupy elementów HTML również z pominięciem hierarchii dokumentu. Reguły te można w sposób dynamiczny zmienić przy pomocy języka JavaScript. Jeśli [...]]]></description>
			<content:encoded><![CDATA[<p>Element w HTML może zawierać atrybut <em>id</em> nadający mu unikatowy identyfikator. Dzięki temu możliwe jest napisanie reguł CSS odnoszących się bezpośrednio do tego elementu z pominięciem hierarchii dokumentu. Atrybut <em>class</em> umożliwia napisanie reguł CSS dla grupy elementów HTML również z pominięciem hierarchii dokumentu. Reguły te można w sposób dynamiczny zmienić przy pomocy języka JavaScript.</p>
<p><span id="more-244"></span></p>
<p>Jeśli kolor elementu o identyfikatorze <em>id_elem</em> chcemy zmienić na czerwony wystarczy w kodzie HTML wpisać:</p>
<pre>
&lt;script type=&quot;text/javascript&quot;&gt;
   var e = document.getElementById(&quot;id_elem&quot;);
   e.style.color = &quot;red&quot;;
&lt;/script&gt;
</pre>
<p>Zmianę koloru elementów <em>p</em> na czerwony w klasie <em>klasa</em> możemy przeprowadzić w taki sposób:</p>
<pre>
&lt;script type=&quot;text/javascript&quot;&gt;
   var e = document.getElementsByTagName(&quot;p&quot;);
   for (var i=0; i&lt;e.length; i++) {
      if (e[i].className.indexOf(&quot;klasa&quot;) != -1) {
         e[i].style.color = &quot;red&quot;;
      }
   }
&lt;/script&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2011/05/identyfikatory-i-klasy-w-css-a-javascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>XML i Python</title>
		<link>http://warczakowski.pl/2011/03/xml-i-python/</link>
		<comments>http://warczakowski.pl/2011/03/xml-i-python/#comments</comments>
		<pubDate>Sun, 20 Mar 2011 20:34:36 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sax]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=193</guid>
		<description><![CDATA[Istnieją dwa podstawowe sposoby przetwarzania dokumentów XML: SAX (Simple API for XML) i DOM (Document Object Model). Standardowa biblioteka Pythona posiada moduły do obsługi obu interfejsów. SAX jest strumieniowym interfejsem odczytywania danych z dokumentów XML opartym na zdarzeniach. Zdarzenia wywoływane są dwukrotnie (na początku i na końcu) podczas napotkania któregokolwiek z elementów dokumentu XML. Wystąpienie [...]]]></description>
			<content:encoded><![CDATA[<p>Istnieją dwa podstawowe sposoby przetwarzania dokumentów XML: SAX (<em>Simple API for XML</em>) i DOM (<em>Document Object Model</em>). Standardowa biblioteka Pythona posiada moduły do obsługi obu interfejsów.</p>
<p>SAX jest strumieniowym interfejsem odczytywania danych z dokumentów XML opartym na zdarzeniach. Zdarzenia wywoływane są dwukrotnie (na początku i na końcu) podczas napotkania któregokolwiek z elementów dokumentu XML. Wystąpienie zdarzenia powoduje wywołanie metody zdefiniowanej przez programistę. Dokument XML jest przetwarzany jednorazowo od początku do końca dokumentu. Takie podejście powoduje, że SAX sprawdza się dobrze przy przetwarzaniu dużych dokumentów nie obciążając mocno pamięci. Obsługa interfejsu SAX realizowana jest w Pythonie przez moduł <em>xml.sax</em>.</p>
<p><span id="more-193"></span></p>
<p>DOM przedstawia dokument w postaci hierarchicznej struktury podobnej do drzewa. Elementy XML w modelu DOM nazywane są węzłami. Na szczycie drzewa mamy węzeł <em>korzeń</em>, który zawiera pozostałe węzły elementów XML. Teksty w elementach są węzłami tekstów, a atrybuty węzłami atrybutów. Również komentarze w dokumencie są węzłami komentarzy. Pomiędzy węzłami istnieje związek hierarchiczny oznaczający, że każdy węzeł (oprócz <em>korzenia</em>) ma dokładnie jednego <em>rodzica</em> i może mieć dowolną liczbę <em>dzieci</em>. Węzły z tymi samymi <em>rodzicami</em> nazywane są <em>rodzeństwem</em>, natomiast węzeł bez <em>dzieci</em> nazywany jest <em>liściem</em>.</p>
<p>Interfejs DOM zanim rozpocznie przetwarzanie dokumentu XML ładuje go do pamięci, dlatego zalecany jest do przetwarzania niewielkich dokumentów ze względu na obciążenie pamięci. W porównaniu do SAX uznawany jest za wolniejszy, ale za to łatwiejszy w obsłudze.</p>
<p>Poniżej przykład jak utworzyć dokument XML przy użyciu interfejsu DOM:</p>
<pre>
# -*- coding: utf-8 -*-
from xml.dom import minidom

# Utworzenie obiektu DOM
DOMimpl = minidom.getDOMImplementation()

# Utworzenie dokumentu
xmldoc = DOMimpl.createDocument(None, &quot;kontakty&quot;, None)
kontakty = xmldoc.documentElement

# Dodanie kontaktu
kontakt = xmldoc.createElement(&quot;kontakt&quot;)
kontakt_atr = xmldoc.createAttribute(&quot;nick&quot;)
kontakt_atr.nodeValue = &quot;janek&quot;
kontakt.setAttributeNode(kontakt_atr)

imie = xmldoc.createElement(&quot;imie&quot;)
imie.appendChild(xmldoc.createTextNode(&quot;Jan&quot;))
kontakt.appendChild(imie)

nazwisko = xmldoc.createElement(&quot;nazwisko&quot;)
nazwisko.appendChild(xmldoc.createTextNode(&quot;Kowalski&quot;))
kontakt.appendChild(nazwisko)

telefon = xmldoc.createElement(&quot;telefon&quot;)
telefon.appendChild(xmldoc.createTextNode(&quot;123 456 789&quot;))
kontakt.appendChild(telefon)

kontakty.appendChild(kontakt)

# Zapisanie dokumentu
plik = open(&quot;kontakty.xml&quot;, &quot;wb&quot;)
plik.write(xmldoc.toxml(&quot;utf-8&quot;))
plik.close()
</pre>
<p>Przykład w jaki sposób przy pomocy DOM dostać się do danych z pliku utworzonego w poprzednim przykładzie:</p>
<pre>
# -*- coding: utf-8 -*-
from xml.dom import minidom

xmldoc = minidom.parse(&quot;kontakty.xml&quot;)
kontakty = xmldoc.getElementsByTagName(&quot;kontakt&quot;)

for kontakt in kontakty:
    nick = kontakt.getAttribute(&quot;nick&quot;)

    imie = kontakt.getElementsByTagName(&quot;imie&quot;)[0]
    imie = imie.firstChild.nodeValue

    nazwisko = kontakt.getElementsByTagName(&quot;nazwisko&quot;)[0]
    nazwisko = nazwisko.firstChild.nodeValue

    telefon = kontakt.getElementsByTagName(&quot;telefon&quot;)[0]
    telefon = telefon.firstChild.nodeValue

    print &quot;Kontakt: %s&quot; % nick
    print &quot;   Imie:     %s&quot; % imie
    print &quot;   Nazwisko: %s&quot; % nazwisko
    print &quot;   Telefon:  %s&quot; % telefon
</pre>
<p>A oto wynik:</p>
<pre>
Kontakt: janek
   Imie:     Jan
   Nazwisko: Kowalski
   Telefon:  123 456 789
</pre>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2011/03/xml-i-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mercurial w systemie Trac</title>
		<link>http://warczakowski.pl/2011/02/mercurial-w-systemie-trac/</link>
		<comments>http://warczakowski.pl/2011/02/mercurial-w-systemie-trac/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 12:04:21 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[trac]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=161</guid>
		<description><![CDATA[Trac jest systemem wspomagającym zarządzanie projektami softwarowymi. Domyślnie dostarcza interface dla systemu Subversion, jednak dzięki dostępnym wtyczkom umożliwia korzystanie z innych systemów kontroli wersji, w tym również z Mercurial. Dla najnowszej, stabilnej wersji 0.12.2 wtyczkę obsługującą Mercurial ściągniemy z repozytorium: svn co http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin Instalacja wtyczki polega na stworzeniu egg: cd mercurial-plugin python setup.py bdist_egg a [...]]]></description>
			<content:encoded><![CDATA[<p>Trac jest systemem wspomagającym zarządzanie projektami softwarowymi. Domyślnie dostarcza <em>interface</em> dla systemu Subversion, jednak dzięki dostępnym wtyczkom umożliwia korzystanie z innych systemów kontroli wersji, w tym również z Mercurial.</p>
<p><span id="more-161"></span></p>
<p>Dla najnowszej, stabilnej wersji 0.12.2 wtyczkę obsługującą Mercurial ściągniemy z repozytorium:</p>
<pre>svn co http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin</pre>
<p>Instalacja wtyczki polega na stworzeniu <em>egg</em>:</p>
<pre>
cd mercurial-plugin
python setup.py bdist_egg
</pre>
<p>a następnie zainstalowaniu go globalnie:</p>
<pre>
easy_install dist/TracMercurial-0.12.0.[x]-py2.[x].egg
</pre>
<p> lub lokalnie w katalogu <em>plugins</em> utworzonego wcześniej środowiska projektu:</p>
<pre>
cp dist/TracMercurial-0.12.0.[x]-py2.[x].egg /sciezka/do/srodowiska/projektu/plugins
</pre>
<p>Domyślnie wtyczka obsługuje repozytoria z plikami w formacie latin-1. Jeśli mamy pliki w formacie latin-2 lub utf-8, przed stworzeniem <em>egg</em> musimy w pliku <em>mercurial-plugin/tracext/hg/backend.py</em> znaleźć i zmienić zmienną środowiskową <em>HGENCODING</em> na właściwe kodowanie:</p>
<pre>os.environ['HGENCODING'] = 'utf-8'</pre>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2011/02/mercurial-w-systemie-trac/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django, Nginx i pfSense</title>
		<link>http://warczakowski.pl/2011/02/django-nginx-i-pfsense/</link>
		<comments>http://warczakowski.pl/2011/02/django-nginx-i-pfsense/#comments</comments>
		<pubDate>Mon, 14 Feb 2011 20:38:53 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Systemy operacyjne]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[pfsense]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=127</guid>
		<description><![CDATA[pfSense w wersji 1.2.3 jest firewallem i routerem bazującym na FreeBSD 7.2. Dzięki wykorzystaniu pakietów FreeBSD możliwe jest zainstalowanie na pfSense lekkiego i szybkiego serwera WWW Nginx do hostowania projektów Django z wykorzystaniem protokołu FastCGI. Po zalogowaniu się na shell wystarczy wydać polecenie: pkg_add -r py26-django Jeśli wystąpią problemy z pobieraniem pakietu z serwera należy [...]]]></description>
			<content:encoded><![CDATA[<p>pfSense w wersji 1.2.3 jest firewallem i routerem bazującym na FreeBSD 7.2. Dzięki wykorzystaniu pakietów FreeBSD możliwe jest zainstalowanie na pfSense lekkiego i szybkiego serwera WWW Nginx do hostowania projektów Django z wykorzystaniem protokołu FastCGI.</p>
<p><span id="more-127"></span></p>
<p>Po zalogowaniu się na shell wystarczy wydać polecenie:</p>
<pre>pkg_add -r py26-django</pre>
<p>Jeśli wystąpią problemy z pobieraniem pakietu z serwera należy zmienić wartość zmiennej <em>PACKAGESITE</em>:</p>
<pre>setenv PACKAGESITE ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-7-stable/Latest/</pre>
<p>i ponownie spróbować zainstalować pakiet <em>py26-django</em> wraz z zależnościami. Powinniśmy otrzymać:</p>
<ul>
<li>python26-2.6.6</li>
<li>libiconv-1.13.1_1</li>
<li>gettext-0.18.1.1</li>
<li>py26-django-1.2.4</li>
</ul>
<p>Aby Django mógł współpracować z Nginx należy wykonać:</p>
<pre>pkg_add -r py26-flup</pre>
<p>a następnie zainstalować serwer WWW:</p>
<pre>pkg_add -r nginx</pre>
<p>W efekcie czego będziemy mieli zainstalowane:</p>
<ul>
<li>py26-setuptools-0.6c11</li>
<li>py26-flup-1.0.2</li>
<li>pcre-8.12</li>
<li>nginx-0.8.54</li>
</ul>
<p>Jeśli w swoim projekcie będziemy korzystać z bazy danych PostgreSQL należy zainstalować <em>psycopg2</em>:</p>
<pre>pkg_add -r py26-psycopg2</pre>
<p>Zainstalowany pakiet <em>py26-psycopg2-2.3.2</em> jest zależny od pakietu <em>postgresql-client-8.4.6</em>, który wykorzystuje bibliotekę <em>libgssapi_krb5.so.9</em>. Bibliotekę <em>libgssapi_krb5.so.9</em> znajdziemy w pakiecie <em>compat7x-i386</em> należącym do FreeBSD w wersji 8:</p>
<pre>setenv PACKAGESITE ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-8-stable/Latest/
pkg_add -r compat7x-i386</pre>
<p>I to wszystko. Po skonfigurowaniu serwera Nginx możemy hostować projekty Django.</p>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2011/02/django-nginx-i-pfsense/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PollXT a pytania otwarte</title>
		<link>http://warczakowski.pl/2010/11/pollxt-a-pytania-otwarte/</link>
		<comments>http://warczakowski.pl/2010/11/pollxt-a-pytania-otwarte/#comments</comments>
		<pubDate>Sat, 27 Nov 2010 16:25:32 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Tworzenie stron WWW]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[joomla]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=71</guid>
		<description><![CDATA[PollXT jest najpopularniejszym komponentem do tworzenia sond lub ankiet w Joomla!. Oprócz pytań zamkniętych z wykorzystaniem checkboxes lub radiobuttons umożliwia tworzenie pytań otwartych, co dla osoby mającej pierwszy kontakt z tym komponentem nie jest takie oczywiste. Aby utworzyć pytanie otwarte wystarczy w zakładce Questions utworzyć nowe pytanie z typem None, a następnie w okienku Options [...]]]></description>
			<content:encoded><![CDATA[<p>PollXT jest najpopularniejszym komponentem do tworzenia sond lub ankiet w Joomla!. Oprócz pytań zamkniętych z wykorzystaniem <em>checkboxes</em> lub <em>radiobuttons</em> umożliwia tworzenie pytań otwartych, co dla osoby mającej pierwszy kontakt z tym komponentem nie jest takie oczywiste.</p>
<p>Aby utworzyć pytanie otwarte wystarczy w zakładce <em>Questions</em> utworzyć nowe pytanie z typem <em>None</em>, a następnie w okienku <em>Options</em> dodać pustą opcję i w okienku <em>Edit option</em> ustawić <em>Freetext</em> na <em>Yes</em>. Wielkość okienka dla pytań otwartych możemy zmienić przy pomocy parametrów <em>Cols</em> i <em>Rows</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2010/11/pollxt-a-pytania-otwarte/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Instant Hacking &#8211; Magnus Lie Hetland</title>
		<link>http://warczakowski.pl/2010/11/instant-hacking/</link>
		<comments>http://warczakowski.pl/2010/11/instant-hacking/#comments</comments>
		<pubDate>Thu, 04 Nov 2010 13:42:37 +0000</pubDate>
		<dc:creator>Wojciech Warczakowski</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://warczakowski.pl/?p=12</guid>
		<description><![CDATA[Jest to krótkie wprowadzenie do sztuki programowania z przykładami napisanymi w języku Python. (Jeśli już wiesz jak programować, a potrzebujesz krótkiego wprowadzenia do języka Python, możesz skorzystać z mojego artykułu Instant Python). Artykuł ten został przetłumaczony na język włoski, japoński, serbski, brazylijski portugalski i holenderski a obecnie trwa tłumaczenie wersji koreańskiej. Strona ta nie traktuje [...]]]></description>
			<content:encoded><![CDATA[<p>Jest to krótkie wprowadzenie do sztuki programowania z przykładami napisanymi w języku <a href="http://www.python.org">Python</a>. (Jeśli już wiesz jak programować, a potrzebujesz krótkiego wprowadzenia do języka Python, możesz skorzystać z mojego artykułu <a href="http://www.hetland.org/python/instant-python.php">Instant Python</a>). Artykuł ten został przetłumaczony na język <a href="http://aleax.supereva.it/Python/ItaPythTut.htm">włoski</a>, <a href="http://www.python.jp/Zope/intro/instant_hacking_jp">japoński</a>, <a href="http://ccc.1asphost.com/walkersplayground/prevodi/ihacking.html">serbski</a>, <a href="http://www.g2ctech.com/artigos/instant-hacking.html">brazylijski portugalski</a> i <a href="http://www.crpg.be/bh/Index.php?pages=2&amp;url=21">holenderski</a> a obecnie trwa tłumaczenie wersji koreańskiej.</p>
<p><span id="more-12"></span></p>
<p>Strona ta nie traktuje o włamywaniu się do systemów komputerowych innych ludzi. Mnie to nie interesuje, więc nie wysyłaj do mnie wiadomości na ten temat.</p>
<p><strong>Uwaga</strong>: Aby zamieszczone przykłady działały poprawnie pisz je do pliku tekstowego a następnie uruchamiaj interpreterem. Nie próbuj uruchamiać programów w trybie interaktywnym &#8211; nie wszystkie będą działać. (Nie pytaj mnie dlaczego. Sprawdź <a href="http://www.python.org/doc">dokumentację</a> lub wyślij email pod adres <a href="mailto:help@python.org">help@python.org</a>).</p>
<h2>Środowisko</h2>
<p>Aby móc programować w Pythonie musisz mieć zainstalowany interpreter. Jest on dostępny na wielu platformach (włącznie z Macintoshem, Uniksem i Windows). Więcej informacji na ten temat znajdziesz na <a href="http://www.python.org">stronie Pythona</a>. Powinieneś również mieć edytor tekstowy (np. <em>emacs</em>, <em>notepad</em> lub podobny).</p>
<h2>Czym jest programowanie?</h2>
<p>Programowanie komputera oznacza przekazywanie mu zestawu instrukcji mówiących co powinien zrobić. Program komputerowy bardzo przypomina przepis na ciasto. Przykład [1]:</p>
<pre><strong>Sernik na kruchym cieście</strong>
    <b>Składniki:</b>
    <span style="text-decoration: underline;">Ciasto:</span>
    30 dag (1 1/2 szklanki) mąki
    13 dag margaryny
    5 dag (3 łyżki) cukru
    4 żółtka

    <span style="text-decoration: underline;">Masa serowa:</span>
    50 dag sera twarogowego tłustego
    20 dag (niepełna szklanka) cukru
    13 dag margaryny
    4-5 jaj
    2 dag (1 łyżka) kaszy manny
    cukier waniliowy lub esencja zapachowa

    <b>Sposób przyrządzenia:</b>
    Margarynę posiekać nożem z mąką, a następnie połączyć z żółtkami i cukrem.
    Ciasto szybko wyrobić ręką i schłodzić w lodówce (co najmniej 30 min).
    Schłodzone ciasto rozwałkować na grubość 1/2 cm i przenieść wałkiem na blachę.
    Ciasto lekko podpiec w gorącym piekarniku (15-20 min).
    Przyrządzić masę serową: ser przepuścić przez maszynkę. Margarynę utrzeć z cukrem,
    żółtkami, kaszą manną i stopniowo dodawanym serem. Ubić sztywną pianę z białek i
    delikatnie połączyć z masą serową. Masę wyłożyć na podpieczony spód i
    piec 30-40 min w umiarkowanie gorącym piekarniku.
</pre>
<p>Oczywiście, żaden komputer tego nie zrozumie, a większość komputerów nie byłaby zdolna do zrobienia sernika nawet, jeśli zrozumiałyby ten przepis. Zatem, co musimy zrobić, aby przepis stał się bardziej zrozumiały dla komputera? Zasadniczo dwie rzeczy. Musimy (1) mówić w taki sposób, aby komputer nas zrozumiał, i (2) mówić o rzeczach, które jest on w stanie wykonać.</p>
<p>Pierwszy punkt oznacza, że musimy użyć języka &#8211; <em>języka programowania</em> zrozumiałego dla naszego interpretera, a drugi punkt oznacza, że nie możemy oczekiwać, aby komputer zrobił sernik &#8211; ale możemy oczekiwać, aby dodawał liczby i wypisywał teksty na ekranie.</p>
<h2>Witaj&#8230;</h2>
<p>Tradycją jest, aby w tutorialach o programowaniu zaczynać zawsze od programu wypisującego na ekranie &#8222;Witaj, świecie!&#8221;. W Pythonie jest to dość proste:</p>
<pre>
    print &quot;Witaj, świecie!&quot;
</pre>
<p>Zasadniczo program ten jest podobny do przedstawionego wcześniej przepisu na sernik (oczywiście jest on znacznie krótszy!). Program mówi komputerowi, co ma zrobić: wypisać na ekranie &#8222;Witaj, świecie!&#8221;. Łatwizna. A gdybyśmy chcieli, aby komputer wykonał coś więcej?</p>
<pre>
    print &quot;Witaj, świecie!&quot;
    print &quot;Żegnaj, świecie!&quot;
</pre>
<p>Niezbyt trudne i niezbyt interesujące. Chcielibyśmy zrobić coś ze składnikami, tak jak w przepisie na sernik. No dobrze. Jakie mamy składniki? Mamy ciągi znaków, jak &#8222;Witaj, świecie!&#8221;, ale również mamy <em>liczby</em>. Zlećmy, więc komputerowi, aby obliczył nam pole prostokąta. Musimy, więc dać mu przepis jak powinien to wykonać:</p>
<pre>
    # Pole prostokąta
    # Składniki:
    szerokosc = 20
    wysokosc = 30

    # Sposób przyrządzenia:
    pole = szerokosc*wysokosc
    print pole
</pre>
<p>Widzisz zapewne podobieństwo (choć niewielkie) do przepisu na sernik. Ale w jaki sposób działa ten program? Po pierwsze, linie rozpoczynające się <code>#</code> nazywane są <em>komentarzem</em> i są ignorowane przez komputer. Jednakże, użycie takich komentarzy może być ważne dla ludzi czytających twoje programy.</p>
<p>Linie takie jak <code>foo = bar</code> nazywane są <em>przypisaniami</em>. Poprzez wyrażenie <code>szerokosc = 20</code> mówimy komputerowi, że szerokosc od tej chwili będzie równe 20. Co znaczy, że &#8222;szerokosc jest równe 20&#8243;? Znaczy to, że zostanie utworzona (bądź ponownie wykorzystana, jeśli już istnieje) <em>zmienna</em> o nazwie &#8222;szerokosc&#8221; i zostanie jej nadana wartość 20. Zatem, jeśli później użyjemy tej zmiennej komputer będzie już znał jej wartość. Dlatego</p>
<pre>
    szerokosc*wysokosc
</pre>
<p>jest w zasadzie tym samym co</p>
<pre>
    20*30
</pre>
<p>które z kolei równe jest 600. Wartość ta następnie zostaje przypisana zmiennej &#8222;pole&#8221;. Ostatnie wyrażenie programu wypisuje na ekran wartość zmiennej &#8222;pole&#8221;, więc po uruchomieniu programu zobaczysz po prostu na ekranie</p>
<pre>
    600
</pre>
<p><b>Uwaga:</b> W niektórych językach już na początku programu musisz powiedzieć komputerowi jakich zmiennych będziesz używał (jakich składników użyjesz do przygotowania sernika) &#8211; w Pythonie zmienne możesz wymyślać w trakcie pisania programu.</p>
<h2>Komunikacja z komputerem</h2>
<p>No dobrze. Możesz już przeprowadzać zarówno proste, jak i dość zaawansowane obliczenia. Możesz, na przykład, napisać program obliczający pole koła zamiast prostokąta:</p>
<pre>
    promien = 30
    print promien*promien*3.14
</pre>
<p>Jednak program ten, podobnie jak poprzedni, jest mało interesujący &#8211; przynajmniej moim zdaniem. Jest on mało elastyczny. No bo, co będzie jeśli interesujące nas koło ma promień 31 stopni? Czy komputer może o tym wiedzieć? Sytuacja przypomina trochę przepis na sernik: &#8222;Masę serową wyłożyć na podpieczony spód i piec 30-40 min. w umiarkowanie gorącym piekarniku.&#8221; Skąd możemy wiedzieć czy po 30 minutach sernik jest już upieczony? Musimy to <em>sprawdzić</em>. W jaki sposób komputer dowie się o promieniu naszego koła? Musi nas o to zapytać&#8230; My zaś musimy w programie powiedzieć mu, aby zapytał się o promień:</p>
<pre>
    promien = input(&quot;Jaki jest promień?&quot;)
    print promien*promien*3.14
</pre>
<p><code>input</code> jest <em>funkcją</em>. (Niedługo nauczysz się tworzyć własne funkcje. <code>input</code> jest funkcją wbudowaną w język Python.) Zwykłe napisanie</p>
<pre>
    input
</pre>
<p>nie zrobi wiele&#8230; Musisz wstawić parę nawiasów na końcu słowa input. Zatem <code>input()</code> powinno zadziałać &#8211; po prostu funkcja będzie czekać, aż użytkownik wpisze promień. Nasza wersja input jest zapewnie bardziej przyjazna, gdyż wcześniej wypisuje na ekran pytanie. Gdy wpiszemy coś pomiędzy nawiasy funkcji, np. pytanie &#8222;Jaki jest promień?&#8221; wtedy <em>przekazujemy parametry</em> do funkcji.  To co wpisujemy w nawiasy funkcji nazywane jest <em>parametrami</em>. W tym przypadku jako parametr do funkcji przekazujemy pytanie, dlatego <code>input</code> wie co wypisać na ekranie zanim otrzyma odpowiedź od użytkownika.</p>
<p>Ale w jaki sposób odpowiedź trafia do zmiennej <code>promien</code>? Funkcja <code>input</code>, kiedy zostanie wywołana, <em>zwraca wartość</em> (tak jak inne funkcje). Nie <em>musisz</em> wykorzystywać tej wartości, jednak w naszym przypadku chcemy z niej skorzystać. Zatem poniższe dwa wyrażenia mają całkiem różne znaczenie:</p>
<pre>
    foo = input
    bar = input()
</pre>
<p><code>foo</code> zawiera funkcję input <em>dosłownie ją samą</em> (zatem możesz użyć takiego wyrażenia <code>foo("Ile masz lat?")</code>; takie zjawisko nazywane jest dynamicznym wywołaniem funkcji), podczas gdy <code>bar</code> zawiera to, co wpisze użytkownik jako odpowiedź.</p>
<h2>Sterowanie</h2>
<p>Możemy już pisać programy wykonujące proste działania (arytmetyczne i drukujące) jak również pobierające dane od użytkownika. Jest to użyteczne, jednak nadal jesteśmy ograniczeni tzw. <em>sekwencyjnym wykonywaniem</em> programu &#8211; rozkazy w programie wykonywane są w ustalonym porządku. Przepisy na ciasta są pisane właśnie w takim sekwencyjnym lub liniowym porządku. A gdybyśmy chcieli powiedzieć komputerowi w jaki sposób powinien sprawdzić, czy sernik jest już upieczony? Jeśli jest, powinien go wyciągnąć z piekarnika, w przeciwnym razie powinien go pozostawić w piekarniku na kolejne pięć minut. W jaki sposób to zrobimy?</p>
<p>To czego potrzebujemy nazywa się <em>sterowanie</em> programem. Program może wykonać dwa działania &#8211; albo wyciągnąć sernik z piekarnika, albo pozostawić go. Możemy wybierać, a <em>warunkiem</em> jest, czy sernik jest już upieczony, czy nie. Technika ta nazywana jest <em>warunkowym wykonaniem</em> programu. Program może wyglądać tak:</p>
<pre>
    temperatura = input(&quot;Jaka jest temperatura sernika?&quot;)

    if temperatura == 30:
        print &quot;Sernik jest już upieczony.&quot;
    else:
        print &quot;Musisz troszkę poczekać na sernik.&quot;
</pre>
<p>Znaczenie programu powinno być oczywiste: Jeśli temperatura jest wyższa niż 30st.C, wówczas wypisz komunikat mówiący użytkownikowi, że sernik jest już upieczony, w przeciwnym razie powiedz użytkownikowi, że musi jeszcze troszkę poczekać.</p>
<p><b>Uwaga:</b> Wcięcia w języku Python są ważne. <em>Bloki</em> w wykonaniu warunkowym (i <em>pętle</em> oraz <em>definicje funkcji</em> &#8211; patrz niżej) muszą mieć wcięcia (wcięcia z tą samą liczbą białych znaków; jeden &lt;tab&gt; liczy się jako 8 spacji) aby interpreter wiedział, w którym miejscu rozpoczynają się, a w którym kończą. Wcięcią również czynią program bardziej czytelny dla ludzi.</p>
<p>Wróćmy do naszych obliczeń pola. Czy widzisz, co ten program robi?</p>
<pre>
    # Program obliczający pole
    print &quot;Witamy w programie obliczającym pole&quot;
    print &quot;------------------------------------&quot;
    print

    # Wydrukuj menu:
    print &quot;Wybierz figurę:&quot;
    print &quot;1  Prostokąt&quot;
    print &quot;2  Koło&quot;

    # Czekaj na wybór użytkownika:
    figura = input(&quot;&gt; &quot;)

    # Oblicz pole:
    if figura == 1:
        wysokosc = input(&quot;Wpisz wysokość: &quot;)
        szerokosc = input(&quot;Wpisz szerokość: &quot;)
        pole = wysokosc*szerokosc
        print &quot;Pole wynosi&quot;, pole
    else:
        promien = input(&quot;Wpisz promien: &quot;)
        pole = 3.14*(promien**2)
        print &quot;Pole wynosi&quot;, pole
</pre>
<p><b>Nowe rzeczy</b> w tym przykładzie&#8230;</p>
<ol>
<li><code>print</code> użyte samo drukuje pustą linię
  </li>
<li><code>==</code> sprawdza, czy dwie rzeczy są równe, w przeciwieństwie do <code>=</code>, które przypisuje wartość z prawej strony do zmiennej po lewej stronie. Jest to ważna różnica!
   </li>
<li><code>**</code> jest pythonowskim operatorem <em>potęgowania</em> &#8211; dlatego promień podniesiony do kwadratu jest zapisany jako <code>promien**2</code>
   </li>
<li><code>print</code> może wydrukować więcej niż jedną rzecz. Po prostu oddziel te rzeczy przecinkami. (Na ekranie będą one oddzielone pojedynczą spacją.)
</li>
</ol>
<p>Program ten jest dosyć prosty &#8211; pyta o liczbę, która mówi mu, czy użytkownik chce obliczyć pole prostokąta, czy koła. Następnie, korzysta z wyrażenia <code>if</code> (wykonanie warunkowe), aby zdecydować, który blok wykorzystać do obliczenia pola. W zasadzie te dwa bloki są takie same jak te, które używaliśmy w poprzednich przykładach. Zauważ, że komentarze czynią kod bardziej czytelnym. Można powiedzieć, że pierwszym przykazaniem programowania jest &#8222;Będziesz pisał komentarze!&#8221;. W każdym<br />
bądź razie &#8211; jest to pożądany nawyk.</p>
<p><b>Ćwiczenie 1</b><br />
Rozszerz program o opcję obliczania pola kwadratów, tak aby użytkownik podawał długość jednego boku. Jest jedna rzecz, którą musisz wiedzieć, aby wykonać to ćwiczenie &#8211; jeśli masz więcej niż dwie możliwości wyboru, możesz zapisać to w taki sposób:</p>
<pre>
    if foo == 1:
        # Zrób coś...
    elif foo == 2:
        # Zrób coś innego...
    elif foo == 3:
        # Zrób coś zupełnie różnego...
    else:
        # Jeśli żaden z warunków nie został spełniony...
</pre>
<p><code>elif</code> jest tajemniczym kodem, który oznacza &#8222;else if&#8221; <code> <img src='http://warczakowski.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </code>. Zatem, jeśli <code>foo</code> równa się jeden, zrób coś; w przeciwnym razie, jeśli <code>foo</code> równa się dwa, zrób coś innego, itd. Możesz dodać do programu również inne opcje &#8211; jak trójkąty lub wielokąty. Wszystko zależy od ciebie.</p>
<h2>Pętle</h2>
<p>Sekwencyjne i warunkowe wykonania są tylko <em>dwoma</em> z <em>trzech</em> fundamentalnych elementów budujących program. Trzecim jest <em>pętla</em>. Proponowałem wcześniej rozwiązanie sprawdzające, czy sernik upiekł się. Jednak nie było ono dosyć wystarczające. No bo, jeśli sernik nie będzie gotowy, to jak następnym razem sprawdzimy czy już się upiekł. Skąd będziemy wiedzieć ile razy musimy to sprawdzać? Prawda jest taka, że nie będziemy wiedzieć. Powinniśmy móc zlecić komputerowi, aby sprawdzał sernik do czasu, aż będzie on upieczony. W jaki sposób to zrobić? Zgadłeś &#8211; użyjemy pętli, lub <em>wykonania powtarzanego</em>.</p>
<p>Python ma dwa rodzaje pętli: pętle <em>while</em> i pętle <em>for</em>. Pętle for są chyba najprostsze. Na przykład:</p>
<pre>
    for jedzenie in &quot;ciasto&quot;, &quot;jajka&quot;, &quot;pomidory&quot;:
        print &quot;Kocham&quot;, jedzenie
</pre>
<p>Co oznacza: dla każdego elementu w liście <code>"ciasto", "jajka", "pomidory"</code> wypisz tekst, że go kochasz. Block wewnątrz pętli jest wykonywany raz dla każdego elementu, i za każdym razem, bieżący element jest podstawiany do zmiennej <code>jedzenie</code> (w tym przypadku). Inny przykład:</p>
<pre>
    for liczba in range(1,100):
        print &quot;Witaj, świecie!&quot;
        print &quot;Tylko&quot;, 100 - liczba, &quot;pozostało...&quot;

    print &quot;Witaj, świecie&quot;
    print &quot;To był ostatni... Fju!&quot;
</pre>
<p>Funkcja <code>range</code> zwraca listę liczb w podanym przedziale (włącznie z pierwszą, bez ostatniej&#8230; W tym przypadku, [1..99]). Zatem, parafrazując:</p>
<blockquote><p>Zawartość pętli jest wykonywana dla (<em>for</em>) każdej <em>liczby</em> w (<em>in</em>) przedziale (<em>range</em>) od (włącznie) <em>1</em> do (bez) <em>100</em>. (Wyjaśnienie tego, co robi ciało pętli i następne wyrażenia pozostawiam jako ćwiczenie dla ciebie.)</p></blockquote>
<p>Jednak to nam nie rozwiązuje naszego problemu z pieczeniem. Jeśli chcemy sprawdzić sernik sto razy, wtedy to rozwiązanie byłoby na miejscu, ale my nie wiemy czy sto razy wystarczy, czy może będzie to za dużo. Po prostu chcemy sprawdzać sernik, <em>kiedy nie jest on wystarczająco gorący</em> (lub do czasu, kiedy <em>stanie się</em> wystarczająco gorący). Dlatego użyjemy <code>while</code>:</p>
<pre>
    # Program pieczenia sernika

    # Pobierz funkcję sleep
    from time import sleep

    print &quot;Rozpocznij pieczenie sernika. (Wrócę za 3 minuty.)&quot;

    # Czekaj 3 minuty (3*60 sekund)...
    sleep(180)

    print &quot;Wróciłeeem...&quot;

    # Jak gorący jest sernik?
    wystarczajaco_goracy = 30

    temperatura = input(&quot;Jak gorący jest sernik? &quot;)
    while temperatura &lt; wystarczajaco_goracy:
        print &quot;Niewystarczająco gorący... Piecz jeszcze chwilę...&quot;
        sleep(30)
        temperatura = input(&quot;OK. Jak gorący jest teraz? &quot;)

    print &quot;Wystarczająco gorący - gotowe!&quot;
</pre>
<p><b>Nowe rzeczy</b> w tym przykładzie&#8230;</p>
<ol>
<li>Niektóre użyteczne funkcje przechowywane są w <em>modułach</em> i mogą być <em>importowane</em>. W tym przykładzie importujemy funkcję <code>sleep</code> (która zasypia na podaną liczbę sekund) z modułu <code>time</code> dostarczanego razem z Pythonem. (Możliwe jest również tworzenie swoich własnych modułów&#8230;)</li>
</ol>
<p><b>Ćwiczenie 2</b><br />
Napisz program sumujący liczby podawane przez użytkownika, do momentu aż suma tych liczb osiągnie 100. Napisz inny program sumujący sto podanych przez użytkownika liczb i wypisujący ich sumę.</p>
<h2>Większe programy &#8211; abstrakcja</h2>
<p>Jeśli chcesz przejrzeć zawartość książki, nie kartkujesz wszystkich stron &#8211; zaglądasz tylko do spisu treści, prawda? Spis treści pokazuje główne tematy książki. Teraz wyobraź sobie pisanie książki kucharskiej. Wiele przepisów takich jak &#8222;Sernik na kruchym cieście&#8221; i &#8222;Sernik po wiedeńsku&#8221; może zawierać podobne rzeczy, tak jak twaróg w tym przypadku. Zapewne nie chciałbyś w każdym przepisie powtarzać jak należy robić twaróg. (Ok&#8230; Nie musisz <em>robić</em> żadnego twarogu&#8230; Jednak bądź dla mnie wyrozumiały dla dobra przykładu <code> <img src='http://warczakowski.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </code>). Pewnie umieściłbyś przepis na twaróg w oddzielnym rozdziale, i po prostu odsyłałbyś do niego w innych przepisach. Zatem, zamiast za każdym razem pisać ciągle cały przepis, wystarczy, że skorzystać z nazwy rozdziału, w którym przepis ten już się znajduje. W programowaniu nazywamy to<br />
<em>abstrakcją</em>.</p>
<p>Czy już mieliśmy z czymś takim do czynienia? Tak. Zamiast dokładnie mówić komputerowi w jaki sposób powinien odebrać odpowiedź od użytkownika (OK &#8211; rzeczywiście nie umielibyśmy tego zrobić&#8230; Ale nie umielibyśmy również zrobić twarogu, zatem&#8230; <code> <img src='http://warczakowski.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </code>) po prostu skorzystaliśmy z funkcji <code>input</code>. Właściwie możemy również tworzyć nasze własne funkcje, aby wykorzystać je w tego rodzaju abstrakcji.</p>
<p>Powiedzmy, że chcemy znaleźć największą liczbę całkowitą, która jest mniejsza od podanej liczby dodatniej. Na przykład, dla liczby 2.7 byłoby to 2. Takie coś nazywane jest &#8222;floor&#8221; danej liczby. (Właściwie można by skorzystać z wbudowanej w Python funkcji <code>int</code>, ale znów, bądź wyrozumiały dla mnie&#8230;) W jaki sposób zrobilibyśmy to? Prostym rozwiązaniem byłoby sprawdzić wszystkie możliwości począwszy od zera:</p>
<pre>
    liczba = input(&quot;Jaka jest liczba? &quot;)

    floor = 0
    while floor &lt; liczba:
        floor = floor+1
    floor = floor-1

    print &quot;Floor liczby&quot;, liczba, &quot;wynosi&quot;, floor
</pre>
<p>Zauważ, że pętla kończy się, kiedy <code>floor</code> już <em>nie jest </em> mniejsze od liczba, a my dodajemy o jeden <em>za dużo</em> do niego. Dlatego później musimy odjąć to jeden. A jeśli chcemy wykorzystać &#8222;floor&#8221; w złożonym matematycznym wyrażeniu? Musielibyśmy pisać całą pętlę dla każdej liczby, która potrzebuje być &#8222;sfloorowana&#8221;. Niezbyt przyjemne&#8230; Zapewne zgadłeś, co zamiast tego zrobimy &#8211; umieścimy wszystko w naszej własnej <em>funkcji</em>, którą nazwiemy &#8222;floor&#8221;:</p>
<pre>
    def floor(liczba):
        wynik = 0
        while wynik &lt; liczba:
            wynik = wynik+1
        wynik = wynik-1
        return wynik
</pre>
<p><b>Nowe rzeczy</b> w tym przykładzie&#8230;</p>
<ol>
<li>Funkcje definiujemy słowem kluczowym <code>def</code>, po czym podajemy nazwę funkcji i w nawiasach jej parametry.</li>
<li>Jeśli funkcja powinna zwracać wartość, wykorzystujemy do tego słowo kluczowe <code>return</code>, które również automatycznie kończy funkcję.</li>
</ol>
<p>Jeśli mamy już zdefiniowaną funkcję, możemy ją wykorzystać w ten oto sposób:</p>
<pre>
    x = 2.7
    y = floor(2.7)
</pre>
<p>Po wykonaniu naszej funkcji <code>y</code> powinno zawierać wartość 2. Możliwe jest również definiowanie funkcji z więcej niż jednym parametrem:</p>
<pre>
    def suma(x,y):
        return x+y
</pre>
<p><b>Ćwiczenie 3</b><br />Napisz funkcję wykorzystującą metodę Euklidesa znajdującą wspólny czynnik dwóch liczb. Powinna ona działać w taki sposób:</p>
<ol>
<li>Masz dwie liczby, a i b, gdzie a jest większe od b</li>
<li>Powtarzaj poniższe działania do momentu, aż b będzie równe zero:
<ol>
<li>przypisz do a wartość b</li>
<li>przypisz do b resztę z dzielenia a (przed zmianą) przez b (przed zmianą)</li>
</ol>
</li>
<li>Zwróć ostatnią wartość a</li>
</ol>
<p><b>Wskazówki:</b></p>
<ul>
<li>Użyj a i b jako parametrów do funkcji</li>
<li>Załóż, że a jest większe od b</li>
<li><em>Reszta</em> z podziału <code>x</code> przez <code>z</code> jest obliczana wyrażeniem <code>x % z</code></li>
<li>Możesz jednocześnie dwóm zmiennym nadać wartość w taki oto sposób: <code>x, y = y, y+1</code>. W tym przypadku <code>x</code> otrzymuje wartość <code>y</code> (wartość przed przypisaniem y+1 do y), a następnie <code>y</code> jest zwiększane o jeden</li>
</ul>
<h2>Więcej o funkcjach</h2>
<p>I co z ćwiczeniem? Trudne? Nadal funkcje onieśmielają cię? Nie martw się &#8211; tematu tego jeszcze nie zamknąłem.</p>
<p>Ten rodzaj abstrakcji, którą używaliśmy podczas tworzenia funkcji często nazywany jest <em>abstrakcją proceduralną</em>, w wielu językach obok słowa <em>function</em> używa się również słowa <em>procedure</em>. Właściwie oba pojęcia są różne, jednak w <em>Pythonie</em> oba nazywane<br />
są funkcjami (ponieważ są one definiowane i używane mniej więcej w ten sam sposób.)</p>
<p>Jaka jest różnica (w innych językach) między funkcjami a procedurami? Jak zauważyłeś w pierwszej części rozważań o funkcjach, funkcje mogą <em>zwracać</em> wartość. Różnica leży w procedurach, które <em>nie</em> zwracają takiej wartości. W wielu przypadkach, taki podział funkcji na dwa typy &#8211; te, które <em>zwracają</em> i te, które <em>nie zwracają</em> wartości &#8211; może być użyteczny.</p>
<p>Funkcja, która <em>nie</em> zwraca wartości (&#8222;procedura&#8221;) wykorzystywana jest jako &#8222;podprogram&#8221;. Wywołujemy taką funkcję, a program wykonuje pewne zadanie, takie jak ubijanie piany z białek lub cokolwiek.<br />
Możemy użyć tę funkcję w wielu miejscach bez przepisywania kodu. (Technikę tę nazywamy <em>ponownym wykorzystaniem kodu (code reuse)</em> &#8211; więcej o tym później.)</p>
<p>Użyteczność takiej funkcji (lub procedury) leży w jej <em>efektach ubocznych</em> &#8211; funkcja zmienia swoje środowisko (poprzez na przykład mieszanie cukru z białkiem i ubijanie go). Spójrzmy na przykład:</p>
<pre>
    def czesc(kto):
        print &quot;Cześć,&quot;, kto

    czesc(&quot;świat&quot;)
    # Wypisze &quot;Cześć, świat&quot;
</pre>
<p>Wypisanie tekstu jest uważane za <em>efekt uboczny</em> i ponieważ jest to wszystko, co ta funkcja wykonuje jest ona uważana za tzw. procedurę. Ale&#8230; W rzeczywistości nie zmieniła ona swojego środowiska, nieprawdaż? Jak może to zrobić? Spróbujmy:</p>
<pre>
    # *Błędnie*
    wiek = 0

    def ustawWiek(a):
        wiek = a

    ustawWiek(100)
    print wiek
    # Drukuje &quot;0&quot;
</pre>
<p>Co tu jest źle? Problemem jest funkcja <code>ustawWiek</code>, która tworzy swoją własną, <em>lokalną</em> zmienną, również nazwaną <code>wiek</code>, która to zmienna widziana jest tylko wewnątrz <code>ustawWiek</code>. Jak możemy to ominąć? Możemy użyć <em>zmiennych globalnych</em>.</p>
<p><b>Uwaga</b>: Zmienne globalne rzadko są wykorzystywane w Pythonie. Prowadzą one do złej struktury kodu, lub do tzw. <em>kodu spaghetti</em>. Ja użyję je jako wprowadzenie do bardziej skomplikowanych technik &#8211; ty, jeśli możesz, unikaj takich zmiennych.</p>
<p>Poprzez poinformowanie interpretera, że zmienna jest globalna (poprzez wyrażenie <code>global wiek</code>) faktycznie mówimy mu, aby użył zmienną utworzoną <em>na zewnątrz</em> funkcji zamiast tworzyć nową, lokalną zmienną. (Zatem, zmienna <em>globalna</em> jest przeciwna do <em>lokalnej</em>.) Nasz nowy program może tak wyglądać:</p>
<pre>
    # *Prawidłowo*, ale niezbyt ładnie
    wiek = 0

    def ustawWiek(a):
        global wiek
        wiek = a

    ustawWiek(100)
    print wiek
    # Drukuje &quot;100&quot;
</pre>
<p>Gdy poznasz objekty (poniżej) zobaczysz, że lepszym sposobem wykonania naszego zadania byłoby użycie objektu z właściwością <code>wiek</code> i metodą <code>ustawWiek</code>. W części o strukturach danych zauważysz również lepsze przykłady funkcji, które zmieniają swoje środowisko.</p>
<p>A co z <em>prawdziwymi funkcjami</em>? Czym jest w rzeczywistości funkcja? Matematyczne funkcje są jak &#8222;maszyny&#8221;, które otrzymują jakieś dane i obliczają z nich wynik. Za każdym razem zwracany będzie ten sam wynik jeśli funkcja otrzyma takie same dane. Przykład:</p>
<pre>
    def kwadrat(x):
        return x*x
</pre>
<p>Powyższe jest tym samym co funkcja matematyczna <i>f</i>(<i>x</i>)=<i>x</i><sup>2</sup>. Zachowuje się jak funkcja dzięki temu, że opiera się <em>tylko</em> na danych wejściowych i <em>nie</em> zmienia w żaden sposób swojego środowiska.</p>
<p>Zarysowałem dwa sposoby tworzenia funkcji: pierwszy typ jest podobny do procedury i nie zwraca wyniku; drugi jest podobny do funkcji matematycznej i nie robi nic (prawie) <em>oprócz</em> zwracania wyniku. Kiedy funkcja zwraca coś powinno być jasne, że to robi. Powinieneś zatem sygnalizować<br />
to poprzez jej nazwę, np. używając tylko rzeczownika &#8222;czystej&#8221; funkcji tak jak <code>kwadrat</code> i trybu rozkazującego dla funkcji-procedur tak jak <code>ustawWiek</code>.</p>
<h2>Więcej składników &#8211; struktury danych</h2>
<p>Wiele już umiesz: jak wprowadzać dane i otrzymywać wyniki, jak tworzyć skomplikowane algorytmy (programy) i przeprowadzać obliczenia arytmetyczne; ale najlepsze jest jeszcze przed tobą.</p>
<p>Jakie składniki do tej pory używaliśmy w naszych programach? Liczby i łańcuchy znaków. Prawda? Troszkę nudne&#8230; Wprowadźmy kilka nowych składników, aby rzeczy stały się bardziej ciekawsze.</p>
<p>Struktury danych są składnikami, które zawierają dane. (Niespodzianka, niespodzianka&#8230;.) Pojedyncza liczba w rzeczywistości nie posiada żadnej struktury, zgadza się? Załóżmy jednak, że chcemy kilka liczb połączyć w jeden składnik, który mógłby mieć jąkąś strukturę. Na przykład, chcielibyśmy mieć listę liczb. Proszę bardzo:</p>
<pre>
    [3,6,78,93]
</pre>
<p>O listach wspomniałem w części o pętlach, ale niewiele o nich powiedziałem. Zatem, w taki sposób możesz je tworzyć. Po prostu wypisz elementy listy, oddziel je przecinkami i zamknij w nawiasach kwadratowych.</p>
<p>Napiszmy teraz przykład, który oblicza liczby pierwsze (liczby, które dzielą się tylko przez siebie lub 1):
</p>
<pre>
    # Oblicz wszystkie liczby pierwsze poniżej 1000
    # (Nie jest to najlepszy sposób wykonania tego, ale...)

    wynik = []
    kandydatki = range(3,1000)
    baza = 2
    produkt = baza

    while kandydatki:
        while produkt &lt; 1000:
            if produkt in kandydatki:
                kandydatki.remove(produkt)
            produkt = produkt+baza
        wynik.append(baza)
        baza = kandydatki[0]
        produkt = baza
        del kandydatki[0]

    wynik.append(baza)
    print wynik
</pre>
<p><b>Nowe rzeczy</b> w tym przykładzie&#8230;</p>
<ol>
<li>Wbudowana funkcja <code>range</code> zwraca listę, która może być wykorzystywana jak inne listy. (Lista ta zawiera pierwszy indeks funkcji, ale nie ostatni.)</li>
<li>Lista może być użyta jako zmienna logiczna. Jeśli nie jest ona pusta, wówczas zwraca <em>true</em> &#8211; jeśli <em>jest</em> pusta, wówczas daje <em>false</em>. Dlatego, <code>while kandydatki</code> oznacza &#8222;kiedy lista o nazwie kandydatki nie jest pusta&#8221; lub prościej &#8222;kiedy nadal są w niej kandydatki&#8221;.</li>
<li>Możesz napisać <code>if jakiśElement in jakiejśLiście</code>, aby sprawdzić, czy dany element znajduje się w tej liście.</li>
<li>Możesz napisać <code>jakaśLista.remove(jakiśElement)</code>, aby usunąć <code>jakiśElement</code> z <code>jakiejśListy</code>.</li>
<li>Możesz dołączyć listę do innej listy pisząc <code>jakaśLista.append(innaLista)</code>. Właściwie, możesz również użyć <code>+</code> (skoro jakaśLista = jakaśLista+innaLista) jednak taki zapis jest mniej efektywny.</li>
<li>Możesz dostać się do wybranego elementu z listy poprzez podanie jego pozycji jako liczby (gdzie pierwszym elementem, trochę dziwnie, jest element <code>0</code>) w nawiasach kwadratowych po nazwie listy. Stąd <code>jakaśLista[3]</code> jest czwartym elementem listy <code>jakaśLista</code>. (Więcej na ten temat niżej.)</li>
<li>Możesz usuwać zmienne wykorzystując słowo kluczowe <code>del</code>. Słowo to może być również wykorzystane do usuwania elementów z listy. Dlatego <code>del jakaśLista[0]</code> usuwa pierwszy element <code>jakiejśListy</code>. Jeśli listą byłby ciąg <code>[1,2,3]</code>, po usunięciu pierwszego elementu otrzymalibyśmy <code>[2,3]</code>.</li>
</ol>
<p>Przed przystąpieniem do wyjaśnienia tajemnic indeksowania elementów listy krótko objaśnię przykład.</p>
<p>Jest to wersja starożytnego algorytmu zwanego &#8222;Sitem Erastotenesa&#8221;. (lub coś blisko tego). Bierze on pod uwagę zestaw (lub w tym przypadku listę) kandydujących liczb, a następnie systematycznie usuwa liczby, o których wiadomo, że nie są liczbami pierwszymi. Skąd o tym wiadomo? Ponieważ są one produktem dwóch innych liczb.</p>
<p>Rozpoczynamy listą kandydatek zawierającą liczby [2..999] &#8211; wiemy, że 1 jest liczbą pierwszą (właściwie, może być lub nie, różne są na ten temat opinie), i chcemy otrzymać wszystkie liczby pierwsze <em>poniżej</em> 1000. (Właściwie, nasza lista kandydatek zawiera liczby w przedziale [3..999], jednak 2 jest również kandydatką, ponieważ jest naszą pierwszą <code>bazą</code>). Mamy również listę nazwaną <code>wynik</code>, która przez cały czas zawiera uaktualnione wyniki. Mamy również zmienną nazwaną<br />
<code>baza</code>. Podczas każdego wykonania algorytmu (rozpoczętego pobraniem kolejnej liczby z &#8222;round&#8221;), usuwamy wszystkie liczby, które są wielokrotnością liczby bazowej (która jest zawsze najmniejszą z kandydatek). Po każdym wykonaniu algorytmu, wiemy, że najmniejsza liczba, która pozostała jest liczbą pierwszą (ponieważ wszystkie liczby, które były produktami mniejszych liczb zostały usunięte &#8211; rozumiesz?). Dlatego, dodajemy ją do wyniku, ustawiamy tę liczbę jako bazę i wyrzucamy ją z listy kandydatek, aby nie powtarzać tego procesu ponownie. Kiedy lista kandydatek będzie pusta, lista wyniku będzie zawierać wszystkie liczby pierwsze. Sprytne, nie?</p>
<p><b>Rzeczy do przemyślenia</b>: Co wyjątkowego jest podczas pierwszego wykonania tego algorytmu? Czy 2, która jest tutaj bazą, jest również usuwana w procesie &#8222;przesiewania&#8221;? Dlaczego? Dlaczego coś takiego nie dzieje się z innymi liczbami bazowymi? Czy możemy być pewni, że <code>produkt</code> jest<br />
zawsze w liście kandydatek, kiedy chcemy go usunąć? Dlaczego?</p>
<p>Teraz &#8211; no właśnie co dalej? Ach tak, indeksowanie. I podział list. Są to sposoby, aby dostać się do indywidualnych elementów listy. Widziałeś już w akcji zwykłe indeksowanie. Jest ono dość proste. Właściwie powiedziałem ci już wszystko, co powinieneś wiedzieć o tym, z wyjątkiem jednej rzeczy: Ujemne indeksy zliczają elementy od <em>końca</em> listy. Zatem, <code>jakaśLista[-1]</code> jest <em>ostatnim</em> elementem <code>jakiejśListy</code>, <code>jakaśLista[-2]</code> jest elementem przedostatnim, i tak dalej.</p>
<p>Podział, jednakże, jest nowy dla ciebie. Jest on podobny do indeksowania z tym wyjątkiem, że otrzymujesz <em>część</em> listy, a nie tylko <em>pojedynczy element</em>. Jak można to zrobić? Np. tak:</p>
<pre>
    jedzenie = [&quot;ciasto&quot;,&quot;ciasto&quot;,&quot;jajka&quot;,&quot;kiełbasa&quot;,&quot;ciasto&quot;]

    print jedzenie[2:4]
    # Wydrukuje &quot;['jajka', 'kiełbasa']&quot;
</pre>
<p>[<em>Więcej o tym później...</em>]</p>
<h2>Więcej o abstrakcji &#8211; obiekty i programowanie orientowane obiektowo</h2>
<p>Jak sugeruje tytuł części, programowanie orientowane obiektowo jest po prostu kolejnym sposobem skupienia szczegółów. Procedury łączą proste wyrażenia w bardziej skomplikowane operacje nadając im nazwę. W OOP, w taki sposób postępujemy z <em>obiektami</em>. (I co, zaskoczyło cię <em>to</em>?) Na przykład, jeśli stworzyliśmy program piekący sernik, zamiast pisania mnóstwa procedur odpowiedzialnych za temperaturę, czas, składniki itd., mogliśmy to wszystko skupić w <em>obiekcie-serniku</em>. Mogliśmy również stworzyć obiekt-piekarnik i obiekt-zegar&#8230; Rzeczy takie jak temperatura mogłyby być atrybutami obiektu-sernika, podczas gdy czas mógłby być odczytywany z obiektu-zegara. Aby nasz program<br />
<em>robił</em> coś, moglibyśmy nauczyć nasze obiekty kilku <em>metod</em>; na przykład, piekarnik mógłby wiedzieć jak piec sernik itd.</p>
<p>Zatem &#8211; jak to zrobimy w Pythonie? Nie możemy bezpośrednio utworzyć obiektu. Zamiast budowania piekarnika, tworzymy <em>przepis</em> opisujący <em>jakie są piekarniki</em>. Ten przepis opisuje klasę<br />
(<em>class</em>) obiektu, który nazywamy piekarnikiem. Bardzo prosta klasa piekarnika może wyglądać tak:</p>
<pre>
    class Piekarnik:
        def wlozSernik(self, sernik):
            self.sernik = sernik 

        def wyjmijSernik(self):
            return self.sernik
</pre>
<p>Wygląda to dziwacznie, czyż nie?</p>
<p><b>Nowe rzeczy</b> w tym przykładzie&#8230;</p>
<ol>
<li>Klasy obiektów definiuje się słowem kluczowym <code>class</code>.</li>
<li>Nazwa klasy zwykle rozpoczyna się z dużej litery, zaś funkcje i zmienne (jak również metody i atrybuty) zaczynają się z małych liter.</li>
<li>Metody (tzn. funkcje i operacje, które wykonuje obiekt) definiuje się w zwykły sposób, ale <em>wewnątrz</em> bloku klasy.</li>
<li>Wszystkie metody obiektu powinny zawierać pierwszy parametr o nazwie <code>self</code> (lub coś podobnego&#8230;) Powód (mam nadzieję) powinien wyjaśnić się za chwilę.</li>
<li>Atrybuty i metody obiektu dostępne są w taki sposób: <code>mojSernik.temperatura = 2</code>, lub <code>piekarnik.wyjmijSernik()</code>.</li>
</ol>
<p>Domyślam się, że niektóre rzeczy są nadal niejasne w tym przykładzie. Na przykład, czym jest to <code>self</code>? I, skoro mamy ten przepis na obiekt (tzn. <em>class</em>), to jak właściwie stworzymy obiekt? Weźmy się najpierw za ostatni punkt. Obiekt tworzy się przez wywołanie nazwy klasy, tak jakby była funkcją:</p>
<pre>
    mojPiekarnik = Piekarnik()
</pre>
<p><code>mojPiekarnik</code> zawiera teraz obiekt <code>Piekarnik</code> i nazywany jest <em>instancją</em> klasy <code>Piekarnik</code>. Załóżmy, że utworzyliśmy klasę <code>Sernik</code>; wówczas moglibyśmy napisać coś takiego:</p>
<pre>
    mojSernik = Sernik()
    mojPiekarnik.wlozSernik(mojSernik)
</pre>
<p><code>mojPiekarnik.sernik</code> zawierałby teraz <code>mojSernik</code>. Jak to możliwe? Ponieważ, kiedy wywołujemy jedną z metod obiektu, pierwszy parametr, zwykle nazywany <code>self</code>, zawsze zawiera obiekt samego siebie. (Sprytne, nie?) Dlatego, linia <code>self.sernik = sernik</code> ustawia <em>atrybut</em> <code>sernik</code> bieżącego obiektu <code>Piekarnika</code> na wartość<br />
<em>parametru</em> <code>sernika</code>. Zauważ, że są to dwie różne rzeczy, nawet jeśli w tym przykładzie obie nazywają się <code>sernik</code>.</p>
<p><b>Odpowiedź do ćwiczenia 3</b><br />
Poniżej podaję bardzo zwięzłą wersję algorytmu:</p>
<pre>
    def euklides(a,b):
        while b:
            a,b = b,a % b
        return a
</pre>
<p><b>Przypisy</b></p>
<p><b>[1]</b>&nbsp;&nbsp; <em><a href="http://k52.kuchniaonline.pl/index.php?id=1389&amp;nr25=61">Kuchnia Online &#8211; Sernik na kruchym cieście</a></em></p>
<p>[Jeśli podoba ci się ten tutorial sprawdź moją książkę <a href="http://hetland.org/writing/beginning-python">Beginning Python</a>.]</p>
]]></content:encoded>
			<wfw:commentRss>http://warczakowski.pl/2010/11/instant-hacking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

