Część I, "Wprowadzenie"

% python
...wiersze z informacjami o prawach autorskich...
>>> "Witaj, sir Robinie!"
'Witaj, sir Robinie!'
>>>                     # By wyjść z programu, użyj skrótu Ctrl+D lub Ctrl+Z bądź zamknij okno

# Plik module1.py
print 'Witaj, module!'

% python module1.py
Witaj, module!


% python
>>> import module1
Witaj, module!
>>>


#!/usr/local/bin/python                      (lub #!/usr/bin/env python)
print 'Witaj, module!'

% chmod +x module1.py

% module1.py
Witaj, module!


% python
>>> 1 / 0
Traceback (innermost last):
   File "<stdin>", line 1, in ?
ZeroDivisionError: integer division or modulo by zero
>>>
>>> x
Traceback (innermost last):
   File "<stdin>", line 1, in ?
NameError: name 'x' is not defined


L = [1, 2]
L.append(L)





Część II, "Typy i operacje"


# Liczby

>>> 2 ** 16                                  # 2 do potęgi 16
65536
>>> 2 / 5, 2 / 5.0                           # Liczba całkowita - odcięcie, liczba zmiennoprzecinkowa - brak odcięcia
(0, 0.40000000000000002)

# Łańcuchy znaków

>>> "mielonka" + "jajka"                     # Konkatenacja
'mielonkajajka'
>>> S = "szynka"
>>> "jajka " + S
'jajka szynka'
>>> S * 5                                    # Powtórzenie
'szynkaszynkaszynkaszynkaszynka'
>>> S[:0]                                    # Pusty wycinek z przodu - [0:0]
''
>>> "zielone %s i %s" % ("jajka", S)         # Formatowanie
'zielone jajka i szynka'

# Krotki

>>> ('x',)[0]                                # Indeksowanie krotki jednoelementowej
'x'
>>> ('x', 'y')[1]                            # Indeksowanie krotki dwuelementowej
'y'

# Listy

>>> L = [1,2,3] + [4,5,6]                    # Operacje na listach
>>> L, L[:], L[:0], L[-2], L[-2:]
([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [], 5, [5, 6])
>>> ([1,2,3]+[4,5,6])[2:4]
[3, 4]
>>> [L[2], L[3]]                             # Pobranie elementów o wartości przesunięcia; przechowanie w liście
[3, 4]
>>> L.reverse( ); L                          # Metoda: odwracanie listy w miejscu
[6, 5, 4, 3, 2, 1]
>>> L.sort( ); L                             # Metoda: sortowanie listy w miejscu
[1, 2, 3, 4, 5, 6]
>>> L.index(4)                               # Metoda: wartość przesunięcia pierwszego elementu 4 (wyszukiwanie)
3

# Słowniki

>>> {'a':1, 'b':2}['b']                      # Indeksowanie słownika po kluczu
2
>>> D = {'x':1, 'y':2, 'z':3}
>>> D['w'] = 0                               # Utworzenie nowego wpisu
>>> D['x'] + D['w']
1
>>> D[(1,2,3)] = 4                           # Krotka użyta jako klucz (jest niezmienna)
>>> D
{'w': 0, 'z': 3, 'y': 2, (1, 2, 3): 4, 'x': 1}
>>> D.keys( ), D.values( ), D.has_key((1,2,3)) # Metody
(['w', 'z', 'y', (1, 2, 3), 'x'], [0, 3, 2, 4, 1], 1)

# Puste obiekty
>>> [[]], ["",[],( ),{},None]                # Dużo niczego: puste obiekty
([[]], ['', [], ( ), {}, None])


>>> L = [1, 2, 3, 4]
>>> L[4]
Traceback (innermost last):
   File "<stdin>", line 1, in ?
IndexError: list index out of range
>>> L[-1000:100]
[1, 2, 3, 4]
>>> L[3:1]
[]
>>> L
[1, 2, 3, 4]
>>> L[3:1] = ['?']
>>> L
[1, 2, 3, '?', 4]


>>> L = [1,2,3,4]
>>> L[2] = []
>>> L
[1, 2, [], 4]
>>> L[2:3] = []
>>> L
[1, 2, 4]
>>> del L[0]
>>> L
[2, 4]
>>> del L[1:]
>>> L
[2]
>>> L[1:2] = 1
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: illegal argument type for built-in operation


>>> X = 'mielonka'
>>> Y = 'jajka'
>>> X, Y = Y, X
>>> X
'jajka'
>>> Y
'mielonka'


>>> D = {}
>>> D[1] = 'a'
>>> D[2] = 'b'
>>> D[(1, 2, 3)] = 'c'
>>> D
{1: 'a', 2: 'b', (1, 2, 3): 'c'}


>>> D = {'a':1, 'b':2, 'c':3}
>>> D['a']
1
>>> D['d']
Traceback (innermost last):
   File "<stdin>", line 1, in ?
KeyError: d
>>> D['d'] = 4
>>> D
{'b': 2, 'd': 4, 'a': 1, 'c': 3}
>>>
>>> L = [0, 1]
>>> L[2]
Traceback (innermost last):
   File "<stdin>", line 1, in ?
IndexError: list index out of range
>>> L[2] = 3
Traceback (innermost last):
   File "<stdin>", line 1, in ?
IndexError: list assignment index out of range


>>> "x" + 1
Traceback (innermost last):
   File "<stdin>", line 1, in ?
TypeError: cannot concatenate 'str' and 'int' objects
>>>
>>> {} + {}
Traceback (innermost last):
   File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
>>>
>>> [].append(9)
>>> "".append('s')
Traceback (innermost last):
   File "<stdin>", line 1, in ?
AttributeError: 'str' object has no attribute 'append'
>>>
>>> {}.keys( )
[]
>>> [].keys( )
Traceback (innermost last):
   File "<stdin>", line 1, in ?
AttributeError: 'list' object has no attribute 'keys'
>>>
>>> [][:]
[]
>>> ""[:]
''


>>> S = "mielonka"
>>> S[0][0][0][0][0]
'm'
>>> L = ['m', 'i']
>>> L[0][0][0]
'm'


>>> S = "jajo"
>>> S = S[0:3] + 'a'
>>> S
'jaja'

>>> S = S[0] + S[1] + S[2] + 'a'
>>> S
'jaja'


>>> me = {'name':('mark', 'e', 'lutz'), 'age':'?', 'job':'engineer'}
>>> me['job']
'engineer'
>>> me['name'][2]
'lutz'


# Plik: maker.py

# -*- coding: utf-8 -*-
file = open('myfile.txt', 'w')
file.write('Witaj, wspaniały świecie!\n')    # Lub: open( ).write( )
file.close( )                                # close nie zawsze jest potrzebne


# Plik: reader.py

# -*- coding: utf-8 -*-
file = open('myfile.txt')                    # 'r' to domyślny tryb otwierania pliku
print file.read()                            # Lub: print open( ).read( )

% python maker.py
% python reader.py
Witaj, wspaniały świecie!

% ls -l myfile.txt
-rwxrwxrwa 1 0 0 19 Apr 13 16:33 myfile.txt


>>> [].__methods__
['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort',...]
>>> dir([])
['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort',...]



Część III, "Instrukcje i składnia"

>>> S = 'mielonka'
>>> for c in S:
...    print ord(c)
...
109
105
101
108
111
110
107
97

>>> x = 0
>>> for c in S: x += ord(c) # Or: x = x + ord(c)
...
>>> x
848

>>> x = []
>>> for c in S: x.append(ord(c))
...
>>> x
[109, 105, 101, 108, 111, 110, 107, 97]

>>> map(ord, S)
[109, 105, 101, 108, 111, 110, 107, 97]


>>> D = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6, 'g':7}
>>> D
{'f': 6, 'c': 3, 'a': 1, 'g': 7, 'e': 5, 'd': 4, 'b': 2}
>>>
>>> keys = D.keys( )
>>> keys.sort( )
>>> for key in keys:
...    print key, '=>', D[key]
...
a => 1
b => 2
c => 3
d => 4
e => 5
f => 6
g => 7

>>> for key in sorted(D):                    # W nowszych wersjach Pythona
...    print key, '=>', D[key]


L = [1, 2, 4, 8, 16, 32, 64]
X = 5

i = 0
while i < len(L):
   if 2 ** X == L[i]:
      print 'pod indeksem', i
      break
   i = i+1
else:
   print X, 'nie odnaleziono'

L = [1, 2, 4, 8, 16, 32, 64]
X = 5

for p in L:
   if (2 ** X) == p:
      print (2 ** X), 'odnaleziono pod indeksem', L.index(p)
      break
else:
   print X, 'nie odnaleziono'

L = [1, 2, 4, 8, 16, 32, 64]
X = 5

if (2 ** X) in L:
   print (2 ** X), 'odnaleziono pod indeksem', L.index(2 ** X)
else:
   print X, 'nie odnaleziono'

X = 5
L = []
for i in range(7): L.append(2 ** i)
print L

if (2 ** X) in L:
   print (2 ** X), 'odnaleziono pod indeksem', L.index(2 ** X)
else:
   print X, 'nie odnaleziono'

X = 5
L = map(lambda x: 2**x, range(7))
print L

if (2 ** X) in L:
   print (2 ** X), 'odnaleziono pod indeksem', L.index(2 ** X)
else:
   print X, 'nie odnaleziono'


Część IV, "Funkcje"


% python
>>> def func(x): print x
...
>>> func("mielonka")
mielonka
>>> func(42)
42
>>> func([1, 2, 3])
[1, 2, 3]
>>> func({'jedzenie': 'mielonka'})
{'jedzenie': 'mielonka'}


# Plik mod.py

def adder(x, y):
   return x + y

print adder(2, 3)
print adder('mielonka', 'jajka')
print adder(['a', 'b'], ['c', 'd'])

% python mod.py
5
mielonkajajka
['a', 'b', 'c', 'd']


# Plik adders.py

# -*- coding: utf-8 -*-
def adder1(*args):
   print 'adder1',
   if type(args[0]) == type(0):              # Liczba całkowita?
      sum = 0                                # Inicjalizacja do wartości zero
   else:                                     # Inaczej sekwencja
      sum = args[0][:0]                      # Wykorzystanie pustego wycinka arg1
   for arg in args:
      sum = sum + arg
   return sum

def adder2(*args):
   print 'adder2',
   sum = args[0]                             # Inicjalizacja do arg1
   for next in args[1:]:
      sum += next                            # Dodanie elementów 2..N
   return sum

for func in (adder1, adder2):
   print func(2, 3, 4)
   print func('mielonka', 'jajka', 'tost')
   print func(['a', 'b'], ['c', 'd'], ['e', 'f'])

% python adders.py
adder1 9
adder1 mielonkajajkatost
adder1 ['a', 'b', 'c', 'd', 'e', 'f']
adder2 9
adder2 mielonkajajkatost
adder2 ['a', 'b', 'c', 'd', 'e', 'f']


# Plik mod.py
def adder(good=1, bad=2, ugly=3):
   return good + bad + ugly
   
print adder( )
print adder(5)
print adder(5, 6)
print adder(5, 6, 7)
print adder(ugly=7, good=6, bad=5)

% python mod.py
6
10
14
18
18


# Plik dicts.py

def copyDict(old):
   new = {}
   for key in old.keys( ):
      new[key] = old[key]
   return new

def addDict(d1, d2):
   new = {}
   for key in d1.keys( ):
      new[key] = d1[key]
   for key in d2.keys( ):
      new[key] = d2[key]
   return new

% python
>>> from dicts import *
>>> d = {1: 1, 2: 2}
>>> e = copyDict(d)
>>> d[2] = '?'
>>> d
{1: 1, 2: '?'}
>>> e
{1: 1, 2: 2}
>>> x = {1: 1}
>>> y = {2: 2}
>>> z = addDict(x, y)
>>> z
{1: 1, 2: 2}


def f1(a, b): print a, b                     # Normalne argumenty

def f2(a, *b): print a, b                    # Zmienna liczba argumentów pozycyjnych

def f3(a, **b): print a, b                   # Zmienna liczba słów kluczowych

def f4(a, *b, **c): print a, b, c            # Tryby mieszane

def f5(a, b=2, c=3): print a, b, c           # Wartości domyślne

def f6(a, b=2, *c): print a, b, c            # Zmienna liczba argumentów pozycyjnych i wartości domyślnych

% python
>>> f1(1, 2)                                 # Dopasowanie po pozycji (kolejność ma znaczenie)
1 2
>>> f1(b=2, a=1)                             # Dopasowanie po nazwie (kolejność nie ma znaczenia)
1 2

>>> f2(1, 2, 3)                              # Dodatkowe argumenty pozycyjne zebrane w krotkę
1 (2, 3)

>>> f3(1, x=2, y=3)                          # Dodatkowe słowa kluczowe zebrane w słownik 
1 {'x': 2, 'y': 3}

>>> f4(1, 2, 3, x=2, y=3)                    # Dodatkowe argumenty obu typów
1 (2, 3) {'x': 2, 'y': 3}

>>> f5(1)                                    # Obie wartości domyślne użyte
1 2 3
>>> f5(1, 4)                                 # Jedna wartość domyślna użyta
1 4 3

>>> f6(1)                                    # Jeden argument: dopasowanie "a"
1 2 ( )
>>> f6(1, 3, 4)                              # Dodatkowe argumenty pozycyjne zebrane w krotkę
1 3 (4,)


# Plik primes.py

# -*- coding: utf-8 -*-
#from __future__ import division

def prime(y):
   if y <= 1:                                # Dla jakiegoś y > 1
      print y, 'nie jest liczbą pierwszą'
   else:
      x = y // 2                             # Przyszły operator / nie działa
      while x > 1:
         if y % x == 0:                      # Bez reszty?
            print y, 'ma czynnik', x
            break                            # Pominięcie else
         x -= 1
      else:
         print y, 'jest liczbą pierwszą'

prime(13); prime(13.0)
prime(15); prime(15.0)
prime(3); prime(2)
prime(1); prime(-3)


% python primes.py
13 jest liczbą pierwszą
13.0 jest liczbą pierwszą
15 ma czynnik 5
15.0 ma czynnik 5.0
3 jest liczbą pierwszą
2 jest liczbą pierwszą
1 nie jest liczbą pierwszą
-3 nie jest liczbą pierwszą


def timer(reps, func, *args):
   import time
   start = time.clock( )
   for i in xrange(reps):
      apply(func, args)
   return time.clock( ) - start


>>> values = [2, 4, 9, 16, 25]
>>> import math

>>> res = []
>>> for x in values: res.append(math.sqrt(x))
...
>>> res
[1.4142135623730951, 2.0, 3.0, 4.0, 5.0]

>>> map(math.sqrt, values)
[1.4142135623730951, 2.0, 3.0, 4.0, 5.0]

>>> [math.sqrt(x) for x in values]
[1.4142135623730951, 2.0, 3.0, 4.0, 5.0]



Część V, "Moduły"


# Plik mymod.py

# -*- coding: utf-8 -*-
def countLines(name):
   file = open(name)
   return len(file.readlines( ))

def countChars(name):
   return len(open(name).read( ))

def test(name):                              # Lub przekazanie obiektu pliku
   return countLines(name), countChars(name) # Lub zwrócenie słownika

% python
>>> import mymod
>>> mymod.test('mymod.py')
(10, 306)


# -*- coding: utf-8 -*-
def countLines(name):
   tot = 0
   for line in open(name): tot += 1
   return tot

def countChars(name):
   tot = 0
   for line in open(name): tot += len(line)
   return tot


# Plik mymod2.py

# -*- coding: utf-8 -*-
def countLines(file):
   file.seek(0)                              # Przewinięcie do początku pliku
   return len(file.readlines( ))

def countChars(file):
   file.seek(0)                              # To samo (przewinięcie, jeśli jest konieczne)
   return len(file.read( ))

def test(name):
   file = open(name)                         # Przekazanie obiektu pliku
   return countLines(file), countChars(file) # Plik otwierany tylko raz

>>> import mymod2
>>> mymod2.test("mymod2.py")
(12, 466)


% python
>>> from mymod import *
>>> countChars("mymod.py")
306


# Plik mymod.py

# -*- coding: utf-8 -*-
def countLines(name):
   file = open(name)
   return len(file.readlines( ))

def countChars(name):
   return len(open(name).read( ))

def test(name):                              # Lub przekazanie obiektu pliku
   return countLines(name), countChars(name) # Lub zwrócenie słownika

if __name__ == '__main__':
   print test('mymod.py')

% python mymod.py
(13, 360)


# Plik myclient.py

from mymod import countLines, countChars
print countLines('mymod.py'), countChars('mymod.py')

% python myclient.py
13 360


import myclient
myclient.countLines(...)

from myclient import countChars
countChars(...)


import myclient
myclient.mymod.countLines(...)

from myclient import mymod
mymod.countChars(...)


# Plik mod1.py
somename = 42

# Plik collector.py
from mod1 import *                           # Zbiera wiele zmiennych
from mod2 import *                           # from przypisuje do moich zmiennych
from mod3 import *

>>> from collector import somename


C:\python25> mkdir mypkg
C:\Python25> move mymod.py mypkg\mymod.py
C:\Python25> edit mypkg\__init__.py
...zapisanie instrukcji print...

C:\Python25> python
>>> import mypkg.mymod
inicjalizacja mypkg
>>> mypkg.mymod.countLines('mypkg\mymod.py')
13
>>> from mypkg.mymod import countChars
>>> countChars('mypkg\mymod.py')
360


Część VI, "Klasy i programowanie zorientowane obiektowo"


# Plik adder.py

# -*- coding: utf-8 -*-
class Adder:
   def add(self, x, y):
      print 'Nie zaimplementowano!'
   def __init__(self, start=[]):
      self.data = start
   def __add__(self, other):                 # Czy w klasach podrzędnych?
      return self.add(self.data, other)      # Czy zwrócić typ?

class ListAdder(Adder):
   def add(self, x, y):
      return x + y

class DictAdder(Adder):
   def add(self, x, y):
      new = {}
      for k in x.keys( ): new[k] = x[k]
      for k in y.keys( ): new[k] = y[k]
      return new

% python
>>> from adder import *
>>> x = Adder( )
>>> x.add(1, 2)
Nie zaimplementowano!
>>> x = ListAdder( )
>>> x.add([1], [2])
[1, 2]
>>> x = DictAdder( )
>>> x.add({1:1}, {2:2})
{1: 1, 2: 2}

>>> x = Adder([1])
>>> x + [2]
Nie zaimplementowano!
>>>
>>> x = ListAdder([1])
>>> x + [2]
[1, 2]
>>> [2] + x
Traceback (innermost last):
   File "<stdin>", line 1, in ?
TypeError: can only concatenate list (not "instance") to list


# Plik adder2.py

# -*- coding: utf-8 -*-
class Adder:
   def __init__(self, start=[]):
      self.data = start
   def __add__(self, other):                 # Przekazanie pojedynczego argumentu
      return self.add(other)                 # Lewa strona jest w self
   def add(self, y):
      print 'Nie zaimplementowano!'

class ListAdder(Adder):
   def add(self, y):
      return self.data + y

class DictAdder(Adder):
   def add(self, y):
      pass                                   # Zmodyfikuj mnie, by użyć self.data zamiast x

x = ListAdder([1, 2 ,3])
y = x + [4, 5, 6]
print y


# Plik mylist.py

# -*- coding: utf-8 -*-
class MyList:
   def __init__(self, start):
      #self.wrapped = start[:]               # Skopiowanie start - brak efektów ubocznych
      self.wrapped = []                      # Upewniamy się, że jest to lista
      for x in start: self.wrapped.append(x)
   def __add__(self, other):
      return MyList(self.wrapped + other)
   def __mul__(self, time):
      return MyList(self.wrapped * time)
   def __getitem__(self, offset):
      return self.wrapped[offset]
   def __len__(self):
      return len(self.wrapped)
   def __getslice__(self, low, high):
      return MyList(self.wrapped[low:high])
   def append(self, node):
      self.wrapped.append(node)
   def __getattr__(self, name):              # Inne składowe: sort, reverse itd.
      return getattr(self.wrapped, name)
   def __repr__(self):
      return repr(self.wrapped)

if __name__ == '__main__':
   x = MyList('mielonka')
   print x
   print x[2]
   print x[1:]
   print x + ['jajka']
   print x * 3
   x.append('a')
   x.sort( )
   for c in x: print c,

% python mylist.py
['m', 'i', 'e', 'l', 'o', 'n', 'k', 'a']
e
['i', 'e', 'l', 'o', 'n', 'k', 'a']
['m', 'i', 'e', 'l', 'o', 'n', 'k', 'a', 'jajka']
['m', 'i', 'e', 'l', 'o', 'n', 'k', 'a', 'm', 'i', 'e', 'l', 'o', 'n', 'k', 'a', 'm', 'i', 'e', 'l', 'o', 'n', 'k', 'a']
a a e i k l m n o


# Plik mysub.py

# -*- coding: utf-8 -*-
from mylist import MyList

class MyListSub(MyList):
   calls = 0                                 # Współdzielona przez instancje
   def __init__(self, start):
      self.adds = 0                          # Różni się w każdej instancji
      MyList.__init__(self, start)

   def __add__(self, other):
      MyListSub.calls = MyListSub.calls + 1  # Licznik dla całej klasy
      self.adds = self.adds + 1              # Liczniki dla instancji
      return MyList.__add__(self, other)

   def stats(self):
      return self.calls, self.adds           # Wszystkie dodawania, moje dodawania

if __name__ == '__main__':
   x = MyListSub('mielonka')
   y = MyListSub('szynka')
   print x[2]
   print x[1:]
   print x + ['jajka']
   print x + ['tost']
   print y + ['bar']
   print x.stats( )

% python mysub.py
e
['i', 'e', 'l', 'o', 'n', 'k', 'a']
['m', 'i', 'e', 'l', 'o', 'n', 'k', 'a', 'jajka']
['m', 'i', 'e', 'l', 'o', 'n', 'k', 'a', 'tost']
['s', 'z', 'y', 'n', 'k', 'a', 'bar']
(3, 2)


>>> class Meta:
...    def __getattr__(self, name):
...       print 'pobierz', name
...    def __setattr__(self, name, value):
...       print 'ustaw', name, value
...
>>> x = Meta( )
>>> x.append
pobierz append
>>> x.spam = "wieprzowina"
ustaw spam wieprzowina
>>>
>>> x + 2
pobierz __coerce__
Traceback (innermost last):
   File "<stdin>", line 1, in ?
TypeError: 'NoneType' object is not callable
>>>
>>> x[1]
pobierz __getitem__
Traceback (innermost last):
   File "<stdin>", line 1, in ?
TypeError: 'NoneType' object is not callable
>>> x[1:5]
pobierz __len__
Traceback (innermost last):
   File "<stdin>", line 1, in ?
TypeError: 'NoneType' object is not callable


% python
>>> from setwrapper import Set
>>> x = Set([1, 2, 3, 4])                    # Wykonuje __init__
>>> y = Set([3, 4, 5])

>>> x & y                                    # __and__, intersect, następnie __repr__
Zbiór:[3, 4]

>>> x | y                                    # __or__, union, następnie __repr__
Zbiór:[1, 2, 3, 4, 5]

>>> z = Set("hallo")                         # __init__ usuwa duplikaty
>>> z[0], z[-1]                              # __getitem__
('h', 'o')

>>> for c in z: print c,                     # __getitem__
...
h a l o

>>> len(z), z                                # __len__, __repr__
(4, Zbiór:['h', 'a', 'l', 'o'])

>>> z & "mello", z | "mello"
(Zbiór:['l', 'o'], Zbiór:['h', 'a', 'l', 'o', 'm', 'e'])


# Plik multiset.py

# -*- coding: utf-8 -*-
from setwrapper import Set

class MultiSet(Set):
   """
   Dziedziczy wszystkie zmienne klasy Set, jednak
   rozszerza intersect oraz union w taki sposób, by
   obsługiwały większą liczbę argumentów. Warto
   zauważyć, że "self" nadal jest pierwszym
   argumentem (przechowanym teraz w argumencie *args).
   Odziedziczone operatory & oraz | wywołują nowe
   metody z dwoma argumentami, jednak przetworzenie
   więcej niż dwóch wymaga wywołania metody, a nie
   wyrażenia.
   """
   
   def intersect(self, *others):
      res = []
      for x in self:                         # Przeszukanie pierwszej sekwencji
         for other in others:                # Dla wszystkich pozostałych argumentów
            if x not in other: break         # Element w każdym z nich?
         else:                               # Nie - wyjście z pętli
            res.append(x)                    # Tak - dodanie elementu na końcu
      return Set(res)

   def union(*args):                         # self to args[0]
      res = []
      for seq in args:                       # Dla wszystkich argumentów
         for x in seq:                       # Dla wszystkich węzłów
            if not x in res:
               res.append(x)                 # Dodanie nowych elementów do wyniku
      return Set(res)


>>> from multiset import *
>>> x = MultiSet([1,2,3,4])
>>> y = MultiSet([3,4,5])
>>> z = MultiSet([0,1,2])

>>> x & y, x | y                             # Dwa argumenty
(Zbiór:[3, 4], Zbiór:[1, 2, 3, 4, 5])

>>> x.intersect(y, z)                        # Trzy argumenty
Zbiór:[]

>>> x.union(y, z)
Zbiór:[1, 2, 3, 4, 5, 0]

>>> x.intersect([1,2,3], [2,3,4], [1,2,3])   # Cztery argumenty
Zbiór:[2, 3]

>>> x.union(range(10))                       # Działa również na innych zbiorach
Zbiór:[1, 2, 3, 4, 0, 5, 6, 7, 8, 9]


# -*- coding: utf-8 -*-
class Lister:
   def __repr__(self):
      return ("<Instancja klasy %s(%s), adres %s:\n%s>" %
               (self.__class__.__name__,     # Nazwa mojej klasy
                self.supers( ),              # Moje klasy nadrzędne
                id(self),                    # Mój adres
                self.attrnames( )) )         # Lista nazwa=wartość
   def attrnames(self):
      ...bez zmian...
   def supers(self):
      result = ""
      first = 1
      for super in self.__class__.__bases__: # Jeden poziom w górę od klasy
         if not first:
            result = result + ", "
         first = 0
         result = result + super.__name__    # name, nie repr(super)
      return result

C:\python\examples> python testmixin.py
<Instancja klasy Sub(Super, Lister), adres 7841200:
      zmienna data3=42
      zmienna data2=jajka
      zmienna data1=mielonka
>


# Plik lunch.py

# -*- coding: utf-8 -*-
class Lunch:
   def __init__(self):                       # Utworzenie/osadzenie klas Customer oraz Employee
      self.cust = Customer( )
      self.empl = Employee( )
   def order(self, foodName):                # Rozpoczęcie symulacji zamówienia klienta Customer
      self.cust.placeOrder(foodName, self.empl)
   def result(self):                         # Zapytanie klienta Customer o jego jedzenie Food
      self.cust.printFood( )

class Customer:
   def __init__(self):                       # Inicjalizacja mojego jedzenia na None
      self.food = None
   def placeOrder(self, foodName, employee): # Złożenie zamówienia pracownikowi Employee
      self.food = employee.takeOrder(foodName)
   def printFood(self):                      # Wyświetlenie nazwy mojego jedzenia
      print self.food.name

class Employee:
   def takeOrder(self, foodName):            # Zwrócenie jedzenia Food o żądanej nazwie
      return Food(foodName)

class Food:
   def __init__(self, name):                 # Przechowanie nazwy jedzenia
      self.name = name

if __name__ == '__main__':
   x = Lunch( )                              # Kod samosprawdzający
   x.order('burrito')                        # Jeśli plik jest wykonywany, nie importowany
   x.result( )
   x.order('pizza')
   x.result( )

% python lunch.py
burrito
pizza


# Plik zoo.py

# -*- coding: utf-8 -*-
class Animal:
   def reply(self): self.speak( )            # Z powrotem do klasy podrzędnej
   def speak(self): print 'mielonka'         # Własny komunikat

class Mammal(Animal):
   def speak(self): print 'hę?'

class Cat(Mammal):
   def speak(self): print 'miau'

class Dog(Mammal):
   def speak(self): print 'hau'

class Primate(Mammal):
   def speak(self): print 'Witaj, świecie!'

class Hacker(Primate): pass                  # Dziedziczy po klasie Primate


# Plik parrot.py

# -*- coding: utf-8 -*-
class Actor:
   def line(self): print self.name + ':', repr(self.says( ))

class Customer(Actor):
   name = 'klient'
   def says(self): return "To już ekspapuga!"

class Clerk(Actor):
   name = 'sprzedawca'
   def says(self): return "nie, wcale nie..."

class Parrot(Actor):
   name = 'papuga'
   def says(self): return None

class Scene:
   def __init__(self):
      self.clerk = Clerk( )                  # Osadzenie instancji
      self.customer = Customer( )            # Scene to kompozyt
      self.subject = Parrot( )
   def action(self):
      self.customer.line( )                  # Delegacja do osadzonych
      self.clerk.line( )
      self.subject.line( )


Część VII, "Wyjątki oraz narzędzia"


# Plik oops.py

# -*- coding: utf-8 -*-
def oops( ):
   raise IndexError

def doomed( ):
   try:
      oops( )
   except IndexError:
      print 'przechwycono błąd indeksu!'
   else:
      print 'nie przechwycono żadnego błędu...'
      
if __name__ == '__main__': doomed( )

% python oops.py
przechwycono błąd indeksu!


# Plik oops.py

# -*- coding: utf-8 -*-
MyError = 'witaj,'

def oops( ):
   raise MyError, 'świecie'

def doomed( ):
   try:
      oops( )
   except IndexError:
      print 'przechwycono błąd indeksu!'
   except MyError, data:
      print 'przechwycono błąd:', MyError, data
   else:
      print 'nie przechwycono żadnego błędu...'

if __name__ == '__main__':
   doomed( )

% python oops.py
przechwycono błąd: witaj, świecie


class MyError: pass

def oops( ):
   raise MyError( )

...reszta pozostaje bez zmian...


% python oop_oops.py
przechwycono błąd: __main__.MyError <__main__.MyError instance at 0x00867550>


# Plik safe2.py

# -*- coding: utf-8 -*-
import sys, traceback

def safe(entry, *args):
   try:
      apply(entry, args)                     # Przechwycenie wszystkiego innego
   except:
      traceback.print_exc( )
      print 'Mam', sys.exc_type, sys.exc_value

import oops
safe(oops.oops)

% python safe2.py
Traceback (innermost last):
   File "safe2.py", line 6, in safe
      apply(entry, args)                     # Przechwycenie wszystkiego innego
   File "oops.py", line 5, in oops
      raise MyError, 'świecie'
witaj,: świecie
Mam witaj, świecie


# Plik safe2_new.py

def safe(entry, *args):
   try:
      entry(*args)                           # Przechwycenie wszystkiego innego
   except:
      traceback.print_exc( )
      print 'Mam', sys.exc_info( ){0], sys.exc_info( )[1]


# Plik bigdir.py: Odnalezienie największego pliku w jednym katalogu

dirname = r'C:\Python25\Lib'
import os, glob

allsizes = []
allpy = glob.glob(os.path.join(dirname, '*.py'))
for filename in allpy:
   filesize = os.path.getsize(filename)
   allsizes.append((filesize, filename))

allsizes.sort( )
print allsizes[:2]
print allsizes[-2:]


# Plik bigtree.py: Odnalezienie największego pliku w całym drzewie katalogów

import sys
if sys.platform[:3] == 'win':
   dirname = r'C:\Python25\Lib'
else:
   dirname = '/usr/lib/python'
import os, glob

allsizes = []
for (thisDir, subsHere, filesHere) in os.walk(dirname):
   for filename in filesHere:
      if filename.endswith('.py'):
         fullname = os.path.join(thisDir, filename)
         fullsize = os.path.getsize(fullname)
         allsizes.append((fullsize, fullname))

allsizes.sort( )
print allsizes[:2]
print allsizes[-2:]


# Plik bigmod.py: Odnalezienie największego pliku źródłowego Pythona w ścieżce wyszukiwania importowanych modułów

import sys, os, pprint
visited = {}
allsizes = []
for srcdir in sys.path:
   for (thisDir, subsHere, filesHere) in os.walk(srcdir):
      thisDir = os.path.normpath(thisDir)
      if thisDir.upper( ) in visited:
         continue
      else:
         visited[thisDir.upper( )] = True
      for filename in filesHere:
         if filename.endswith('.py'):
            pypath = os.path.join(thisDir, filename)
            try:
               pysize = os.path.getsize(pypath)
            except:
               print 'pomijam', pypath
            allsizes.append((pysize, pypath))

allsizes.sort( )
pprint.pprint(allsizes[:3])
pprint.pprint(allsizes[-3:])


# Plik summer1.py: Sumowanie rozdzielonych przecinkami kolumn w pliku tekstowym

filename = 'data.txt'
sums = {}

for line in open(filename):
   cols = line.split(',')
   nums = [int(col) for col in cols]
   for (ix, num) in enumerate(nums):
      sums[ix] = sums.get(ix, 0) + num

for key in sorted(sums):
   print key, '=', sums[key]


# Plik summer2.py: Podobnie do poprzedniego przykładu, jednak dla sum wykorzystuje listy, a nie słowniki

import sys
filename = sys.argv[1]
numcols = int(sys.argv[2])
totals = [0] * numcols

for line in open(filename):
   cols = line.split(',')
   nums = [int(x) for x in cols]
   totals = [(x + y) for (x, y) in zip(totals, nums)]

print totals


# Plik regtest.py: Testowanie regresji w danych wyjściowych zbioru skryptów

import os
testscripts = [dict(script='test1.py', args=''),
               dict(script='test2.py', args='spam')]

for testcase in testscripts:
   commandline = '%(script)s %(args)s' % testcase
   output = os.popen(commandline).read( )
   result = testcase['script'] + '.result'
   if not os.path.exists(result):
      open(result, 'w').write(output)
      print 'Utworzony:', result
   else:
      priorresult = open(result).read( )
      if output != priorresult:
         print 'NIEPOWODZENIE:', testcase['script']
         print output
      else:
         print 'Przeszedł:', testcase['script']


# Plik gui1.py: Utworzenie graficznego interfejsu użytkownika za pomocą Tkinter z przyciskami zmieniającymi kolor oraz wielkość

# -*- coding: utf-8 -*-
from Tkinter import *
import random
fontsize = 25
colors = ['red', 'green', 'blue', 'yellow', 'orange', 'white', 'cyan', 'purple']

def reply(text):
   print text
   popup = Toplevel( )
   color = random.choice(colors)
   Label(popup, text='Okno wyskakujące', bg='black', fg=color).pack( )
   L.config(fg=color)

def timer( ):
   L.config(fg=random.choice(colors))
   win.after(250, timer)

def grow( ):
   global fontsize
   fontsize += 5
   L.config(font=('arial', fontsize, 'italic'))
   win.after(100, grow)

win = Tk( )
L = Label(win, text='Mielonka', font=('arial', fontsize, 'italic'), fg='yellow', bg='navy', relief=RAISED)
L.pack(side=TOP, expand=YES, fill=BOTH)
Button(win, text='Naciśnij', command=(lambda: reply('red'))).pack(side=BOTTOM, fill=X)
Button(win, text='Licznik', command=timer).pack(side=BOTTOM, fill=X)
Button(win, text='Powiększ' , command=grow).pack(side=BOTTOM, fill=X)
win.mainloop( )


# Plik gui2.py: Podobnie do poprzedniego przykładu, ale wykorzystuje klasy, tak by każde okno miało własne informacje o stanie

# -*- coding: utf-8 -*-
from Tkinter import *
import random

class MyGui:
   """
   Graficzny interfejs użytkownika z przyciskami zmieniającymi kolor i powiększającymi napis
   """

   colors = ['blue', 'green', 'orange', 'red', 'brown', 'yellow']
   def __init__(self, parent, title='Okno wyskakujące'):
      parent.title(title)
      self.growing = False
      self.fontsize = 10
      self.lab = Label(parent, text='Gui1', fg='white', bg='navy')
      self.lab.pack(expand=YES, fill=BOTH)
      Button(parent, text='Mielonka', command=self.reply).pack(side=LEFT)
      Button(parent, text='Powiększ', command=self.grow).pack(side=LEFT)
      Button(parent, text='Zatrzymaj', command=self.stop).pack(side=LEFT)

   def reply(self):
      "losowa modyfikacja koloru przyciku po naciśnięciu przycisku Mielonka"
      self.fontsize += 5
      color = random.choice(self.colors)
      self.lab.config(bg=color, font=('courier', self.fontsize, 'bold italic'))

   def grow(self):
      "po naciśnięciu przycisku Powiększ podpis zaczyna rosnąć"
      self.growing = True
      self.grower( )
   
   def grower(self):
      if self.growing:
         self.fontsize += 5
         self.lab.config(font=('courier', self.fontsize, 'bold'))
         self.lab.after(500, self.grower)

   def stop(self):
      "po naciśnięciu przycisku Zatrzymaj przycisk przestaje rosnąć"
      self.growing = False

class MySubGui(MyGui):
   colors = ['black', 'purple']              # Można dostosować w celu modyfikacji kolorów do wyboru

MyGui(Tk( ), 'main')
MyGui(Toplevel( ))
MySubGui(Toplevel( ))
mainloop( ) 


# Plik mailscan.py: Narzędzie do przeglądania folderu poczty przychodzącej oraz utrzymywania jej

# -*- coding: utf-8 -*-

"""
przegląda skrzynkę e-mailową POP, pobierając tylko
nagłówki i pozwalając na usuwanie bez pobierania
pełnej wiadomości
"""

import poplib, getpass, sys

mailserver = 'nazwa serwera POP naszej poczty'           # pop.rmi.net
mailuser = 'identyfikator użytkownika poczty'            # brian
mailpasswd = getpass.getpass('Hasło dla %s?' % mailserver)

print 'Łączenie...'
server = poplib.POP3(mailserver)
server.user(mailuser)
server.pass_(mailpasswd)

try:
   print server.getwelcome( )
   msgCount, mboxSize = server.stat( )
   print 'W skrzynce jest', msgCount, 'wiadomości e-mail, rozmiar ', mboxSize
   msginfo = server.list( )
   print msginfo
   for i in range(msgCount):
      msgnum = i+1
      msgsize = msginfo[1][i].split( )[1]
      resp, hdrlines, octets = server.top(msgnum, 0)     # Pobranie tylko nagłówków
      print '-'*80
      print '[%d: octets=%d, size=%s]' % (msgnum, octets, msgsize)
      for line in hdrlines: print line

      if raw_input('Wyświetlić?') in ['y', 'Y']:
         for line in server.retr(msgnum)[1]: print line  # Pobranie całej wiadomości
      if raw_input('Usunąć?') in ['y', 'Y']:
         print 'usuwanie'
         server.dele(msgnum)                             # Usunięcie z serwera
      else:
         print 'pomijanie'
finally:
   server.quit( )                                        # Należy odblokować skrzynkę mbox
raw_input('Żegnaj.')                                     # Zachowanie okna


# Plik cgigreet.py: Skrypt CGI po stronie klienta wchodzący w interakcję z przeglądarką

#!/usr/bin/python
import cgi
form = cgi.FieldStorage( )                   # Przetworzenie danych formularza
print "Content-type: text/html\n"            # Nagłówek i pusty wiersz
print "<HTML>"
print "<title>Strona odpowiedzi</title>"     # Strona html z odpowiedzią
print "<BODY>"
if not form.has_key('user'):
   print "<h1>Kim jesteś?</h1>"
else:
   print "<h1>Witaj, <i>%s</i>!</h1>" % cgi.escape(form['user'].value)
print "</BODY></HTML>"


# Plik makesqldb.py: Skrypt bazy danych zapełniający bazę MySQL i wykonujący do niej zapytania

# -*- coding: utf-8 -*-
from MySQLdb import Connect
conn = Connect(host='localhost', user='root', passwd='darling')
curs = conn.cursor( )
try:
   curs.execute('drop database testpeopledb')
except:
   pass                                      # Nie istniała

curs.execute('create database testpeopledb')
curs.execute('use testpeopledb')
curs.execute('create table people (name char(30), job char(10), pay int(4))')

curs.execute('insert people values (%s, %s, %s)', ('Robert', 'programista', 50000))
curs.execute('insert people values (%s, %s, %s)', ('Zuzanna', 'programista', 60000))
curs.execute('insert people values (%s, %s, %s)', ('Anna', 'menedżer', 40000))

curs.execute('select * from people')
for row in curs.fetchall( ):
   print row

curs.execute('select * from people where name = %s', ('Robert',))
print curs.description
colnames = [desc[0] for desc in curs.description]
while True:
   print '-' * 30
   row = curs.fetchone( )
   if not row: break
   for (name, value) in zip(colnames, row):
      print '%s => %s' % (name, value)

conn.commit( )                               # Zapisanie wstawionych rekordów


# Plik makedb.py: Skrypt bazy danych wypełniający obiekt shelve obiektami Pythona

# -*- coding: utf-8 -*-
rec1 = {'name': {'first': 'Robert', 'last': 'Kowalski'},
        'job': ['programista', 'menedżer'],
        'age': 40.5}

rec2 = {'name': {'first': 'Zuzanna', 'last': 'Zielona'},
        'job': ['menedżer'],
        'age': 35.0}

import shelve
db = shelve.open('dbfile')
db['bob'] = rec1
db['sue'] = rec2
db.close( )


# Plik updatedb.py: Skrypt bazy danych wyświetlający i uaktualniający obiekt shelve utworzony w poprzednim skrypcie

# -*- coding: utf-8 -*-
import shelve
db = shelve.open('dbfile')
for key in db:
   print key, '=>', db[key]

bob = db['bob']
bob['age'] += 1
db['bob'] = bob
db.close( )