*** Strona 162-163 ***************************************************************

>>> class FirstClass:                 # definiowanie obiektu klasy
...     def setdata(self, value):     # definiowanie metod klasy
...         self.data = value         # self jest egzemplarzem
...     def display(self):        
...         print self.data           # self.data (dla danego egzemplarza)

>>> x = FirstClass()                  # tworzenie dwch egzemplarzy
>>> y = FirstClass()                  # kady jest now przestrzeni nazw

>>> x.setdata("King Arthur")          # wywoanie metody: self jest x lub y
>>> y.setdata(3.14159)                # uruchomienie: FirstClass.setdata(y, 3.14159)

>>> x.display()                       # self.data rni si w kadym egzemplarzu
King Arthur
>>> y.display()
3.14159

>>> x.data = "Nowe dane"              # mona pobra lub ustawi atrybuty
>>> x.display()                       # take na zewntrz klasy
Nowe dane


*** Strona 164-165 ***************************************************************

>>> class SecondClass(FirstClass):               # dziedziczy setdata
...     def display(self):                       # zmienia display
...         print 'Obecne dane = "%s"' % self.data

>>> z = SecondClass()
>>> z.setdata(42)             # setdata znalezione w FirstClass
>>> z.display()               # znajduje zastpion metod w SecondClass
Obecne dane = "42"

>>> x.display()               # x jest nadal egzemplarzem FirstClass (stary komunikat)
Nowe dane


*** Strona 165-166 ***************************************************************

>>> class ThirdClass(SecondClass):          # is-a SecondClass
...     def __init__(self, value):          # dziaa na "ThirdClass(value)"
...         self.data = value
...     def __add__(self, other):           # dziaa na "self + other"
...         return ThirdClass(self.data + other)
...     def __mul__(self, other):
...         self.data = self.data * other   # dziaa na "self * other"

>>> a = ThirdClass("abc")  # nowe wywoanie __init__
>>> a.display()            # metoda odziedziczona 
Obecne dane = "abc"

>>> b = a + 'xyz'          # nowe wywoanie __add__: tworzy nowy egzemplarz
>>> b.display()
Obecne dane = "abcxyz"

>>> a * 3                  # nowe wywoanie __mul__: zmienia egzemplarz 
>>> a.display()
Obecne dane = "abcabcabc"


*** Strona 168 *******************************************************************

# poniszy kod naley wpisa w trybie interakcyjnym lub zaimportowa z moduu

class aSuperclass: pass

class Subclass(aSuperclass):          # definicja klasy podrzdnej
    data = 'mielonka'                 # przypisanie atrybutu klasy
    def __init__(self, value):        # przypisanie atrybutu klasy
        self.data = value             # przypisanie atrybutu egzemplarza
    def display(self):
        print self.data, Subclass.data      # egzemplarz, klasa

>>> x = Subclass(1)          # tworzy dwa egzemplarze obiektw
>>> y = Subclass(2)          # kady ma swoje wasne dane ("data")
>>> x.display(); y.display() # "self.data" inne, "Subclass.data" takie same
1 mielonka
2 mielonka


*** Strona 169 *******************************************************************

class NextClass:                    # definiowanie klasy
    def printer(self, text):        # definiowanie metody
        print text

>>> x = NextClass()                 # tworzenie egzemplarza
>>> x.printer('Hello world!')       # wywoanie jego metody
Hello world!

>>> NextClass.printer(x, 'Hello world!')   # metoda klasy
Hello world!


*** Strona 171 *******************************************************************

>>> class Super:
...     def method(self):
...         print 'in Super.method'
...
>>> class Sub(Super):
...     def method(self):                 # zastpienie metody
...         print 'starting Sub.method'   # tu dodanie dziaa
...         Super.method(self)            # startuje dziaanie domylne
...         print 'ending Sub.method'
...

>>> x = Super()        # tworzenie egzemplarza Super
>>> x.method()         # uruchomienie Super.method
in Super.method

>>> x = Sub()          # tworzenie egzemplarza Sub
>>> x.method()         # uruchamienie Sub.method, wywoujcego Super.method
starting Sub.method
in Super.method
ending Sub.method


*** Strona 172 *******************************************************************

# plik specialize.py

class Super:
    def method(self):
        print 'in Super.method'      # domylne
    def delegate(self):
        self.action()                # oczekiwane

class Inheritor(Super):
    pass

class Replacer(Super):
    def method(self):
        print 'in Replacer.method'

class Extender(Super):
    def method(self):
        print 'starting Extender.method'
        Super.method(self)
        print 'ending Extender.method'

class Provider(Super):
    def action(self):
        print 'in Provider.action'

if __name__ == '__main__':
    for klasa in (Inheritor, Replacer, Extender):
        print '\n' + klasa.__name__ + '...'
        klasa().method()
    print '\nProvider...'
    Provider().delegate()

% python specialize.py

Inheritor...
in Super.method

Replacer...
in Replacer.method

Extender...
starting Extender.method
in Super.method
ending Extender.method

Provider...
in Provider.action


*** Strona 173-176 ***************************************************************

# number.py

class Number:
    def __init__(self, start):             # w Number(start)
        self.data = start
    def __sub__(self, other):              # w egzemplarz - other
        return Number(self.data - other)   # wynik w nowym egzemplarzu

>>> from number import Number              # pobiera klas z moduu
>>> X = Number(5)                          # wywouje Number.__init__(X, 5)
>>> Y = X - 2                              # wywouje Number.__sub__(X, 2)
>>> Y.data
3


>>> class indexer:
...     def __getitem__(self, index):
...         return index ** 2
...
>>> X = indexer()
>>> for i in range(5):
...     print X[i],                  # X[i] wywouje __getitem__(X, i)
...
0 1 4 9 16


>>> class stepper:
...     def __getitem__(self, i):
...         return self.data[i]
...
>>> X = stepper()                 # X jest obiektem kroczcym
>>> X.data = "Mielonka"
>>>
>>> for item in X:                # ptle for wywouj __getitem__
...     print item,               # dla pozycji indeksowych 0..N
...
M i e l o n k a
>>>
>>> 'l' in X                      # operator 'in' take wywouje __getitem__
1


>>> class empty:
...     def __getattr__(self, attrname):
...         if attrname == "age":
...             return 36
...         else:
...             raise AttributeError, attrname
...
>>> X = empty()
>>> X.age
36
>>> X.name
Traceback (innermost last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 6, in __getattr__
AttributeError: name


>>> class adder:
...     def __init__(self, value=0):
...        self.data = value                   # inicjowanie danych
...     def __add__(self, other):
...         self.data = self.data + other      # dodawanie other w miejscu
...     def __repr__(self):
...         return `self.data`                 # przeksztacanie na acuch
...
>>> X = adder(1)        # __init__
>>> X + 2; X + 2        # __add__
>>> X                   # __repr__
5


*** Strona 177 *******************************************************************

>>> class super:
...     def hello(self):
...         self.data1 = "mielonka"
...
>>> class sub(super):
...     def howdy(self):
...         self.data2 = "jajka"
...
>>> X = sub()                    # tworzy now przestrze nazw (sownik)
>>> X.__dict__
{}
>>> X.hello()                    # zmienia przestrze nazw egzemplarza
>>> X.__dict__
{'data1': 'mielonka'}

>>> X.howdy()                    # zmienia przestrze nazw egzemplarza
>>> X.__dict__
{'data2': 'jajka', 'data1': 'mielonka'}

>>> super.__dict__
{'hello': <function hello at 88d9b0>, '__doc__': None}

>>> sub.__dict__
{'__doc__': None, 'howdy': <function howdy at 88ea20>}

>>> X.data3 = "tost"
>>> X.__dict__
{'data3': 'tost', 'data2': 'jajka', 'data1': 'mielonka'}


*** Strona 179-180 ***************************************************************

# plik pracownicy.py

class Pracownik:
    def __init__(self, nazwa, placa=0):
        self.nazwa   = nazwa
        self.placa = placa
    def dajPodwyzke(self, procent):
        self.placa = self.placa + (self.placa * procent)
    def praca(self):
        print self.nazwa, "robi nadzienie"
    def __repr__(self):
        return "<Pracownik: nazwa=%s, placa=%s>" % (self.nazwa, self.placa)

class Szef(Pracownik):
    def __init__(self, nazwa):
        Pracownik.__init__(self, nazwa, 50000)
    def praca(self):
        print self.nazwa, "robi jedzonko"

class Obsluga(Pracownik):
    def __init__ (self, nazwa):
        Pracownik.__init__(self, nazwa, 40000)
    def praca(self):
        print self.nazwa, "obsluguje klientow"

class PizzaRobot(Szef):
    def __init__(self, nazwa):
        Szef.__init__(self, nazwa)
    def praca(self):
        print self.nazwa, "robi pizze"

if __name__ == "__main__":
    bob = PizzaRobot('bob')      # utworzenie robota o nazwie bob
    print bob                    # uruchomienie odziedziczonej __repr__
    bob.dajPodwyzke(0.20)        # podwyszenie pensji boba o 20% 
    print bob; print

for klasa in Pracownik, Szef, Obsluga, PizzaRobot:
    obj = klasa(klasa.__name__)
    obj.praca()


C:\python\examples> python pracownicy.py
<Pracownik: nazwa=bob, placa=50000>
<Pracownik: nazwa=bob, placa=60000.0>

Pracownik robi nadzienie
Szef robi jedzonko
Obsluga obsluguje klientow
PizzaRobot robi pizze


*** Strona 180-181 ***************************************************************

# plik pizzasklep.py

from pracownicy import PizzaRobot, Obsluga

class Klient:
    def __init__(self, nazwa):
        self.nazwa = nazwa
    def zamowienie(self, obsluga):
        print self.nazwa, "zamawia u", obsluga
    def placic(self, obsluga):
        print self.nazwa, "placi za pozycje do", obsluga

class Piec:
    def piecze(self):
        print "piec piecze"
class PizzaSklep:
    def __init__(self):
        self.obsluga = Obsluga('Pat')       # osadza inne obiekty
        self.szef    = PizzaRobot ('Bob')   # robot o imieniu bob
        self.piec    = Piec()
    def zamowienie(self, nazwa):
        klient = Klient(nazwa)              # uaktywnia inne obiekty
        klient.zamowienie(self.obsluga)     # zamwienia klientw u obsugi
        self.szef.praca()
        self.piec.piecze()
        klient.placic(self.obsluga)

if __name__ == "__main__":
    scena = PizzaSklep()                   # tworzenie kompozycji
    scena.zamowienie('Homer')              # symulacja zamwienia Homera
    print '...'
    scena.zamowienie('Shaggy')             # symulacja zamwienia Shaggy


C:\python\examples> python pizzasklep.py
Homer zamawia u <Pracownik: nazwa=Pat, pensja=40000>
Bob robi pizze
piec piecze
Homer placi za pozycje do <Pracownik: nazwa=Pat, placa=40000>
...
Shaggy zamawia u <pracownik: nazwa=Pat, placa=40000>
Bob robi pizze
piec piecze
Shaggy placi za pozycje do <Pracownik: nazwa=Pat, placa=40000>


*** Strona 182-183 ***************************************************************

import pickle
obiekt = jakasKlasa()
plik   = open(nazwa_pliku, 'w')      # tworzenie pliku zewntrznego
pickle.dump(obiekt, plik)            # zapis obiektu w pliku

plik   = open(nazwa_pliku, 'r')
obiekt = pickle.load(plik)           # odtworzenie obiektu z pliku


import shelve
obiekt = jakasKlasa()
baza   = shelve.open('nazwa_pliku')
baza['klucz'] = obiekt          # zapis z kluczem
obiekt = baza['klucz']          # odtworzenie


# plik trace.py

class wrapper:
    def __init__(self, object):
        self.wrapped = object                      # zapisuje obiekt
    def __getattr__(self, attrname):
        print 'Trace:', attrname                   # ledzi pobranie
        return getattr(self.wrapped, attrname)     # pobranie delegacji

>>> from trace import wrapper
>>> x = wrapper([1,2,3])              # opakowanie listy
>>> x.append(4)                       # delegacja do metody listy
Trace: append
>>> x.wrapped                         # wydruk czonka
[1, 2, 3, 4]

>>> x = wrapper({"a": 1, "b": 2})     # opakowanie sownika
>>> x.keys()                          # delegacja do metody sownika
Trace: keys
['a', 'b']


# plik set.py

class Set:
    def __init__(self, value = []):     # konstruktor
        self.data = []                  # zarzdza list
        self.concat(value)

    def intersect(self, other):         # other jest dowoln sekwencj
        res = []                        # self jest przedmiotem
        for x in self.data:
            if x in other:              # wskazuje wsplne pozycje
                res.append(x)
            return Set(res)             # zwraca nowy Set

    def union(self, other):             # other jest dowoln sekwencj
        res = self.data[:]              # kopia danej listy
        for x in other:                 # dodawanie pozycji do other
            if not x in res: 
               res.append(x)
        return Set(res)

    def concat(self, value):            # value: list, Set...
        for x in value:                 # usuwa duplikaty
           if not x in self.data:
                self.data.append(x)

    def __len__(self):          return len(self.data)        # len(self)
    def __getitem__(self, key): return self.data[key]        # self[i]
    def __and__(self, other):   return self.intersect(other) # self & other
    def __or__(self, other):    return self.union(other)     # self | other
    def __repr__(self):         return 'Set:' + `self.data`  # print


*** Strona 184-186 ***************************************************************

>>> class Mielonka:
...     def __init__(self):              # brak __repr__
...         self.data1 = "jedzenie"
...
>>> X = Mielonka()
>>> print X                              # format domylny: klasa, adres
<Mielonka instance at 87f1b0>


# plik mytools.py

# Klasa Lister moe by wmieszana do dowolnej klasy 
# w zakresie zapewnienia formatowanego wydruku egzemplarzy
# za pomoc dziedziczenia zakodowanej tu metody __repr__;
# self jest egzemplarzem najniszej klasy;

class Lister:
   def __repr__(self):
       return ("<Instance of %s, address %s:\n%s>" %
                         (self.__class__.__name__,     # nazwa mojej klasy
                          id(self),                    # mj adres
                          self.attrnames()) )          # lista nazwa=warto
   def attrnames(self):
       result = ''
       for attr in self.__dict__.keys():   # skanuje sownik egzemplarza
           if attr[:2] == '__':
               result = result + "\tname %s=<built-in>\n" % attr
           else:
               result = result + "\tname %s=%s\n" % (attr, self.__dict__[attr])
       return result


# plik testmixin.py

from mytools import Lister       # otrzymanie klasy narzdzi

class Super:
    def __init__(self):          # superklasa __init__
       self.data1 = "mielonka"

class Sub(Super, Lister):        # wmieszanie __repr__
    def __init__(self):          # Lister ma dostp do self
        Super.__init__(self)
        self.data2 = "jajka"     # wicej attr przykadu
        self.data3 = 42

if __name__ == "__main__":
    X = Sub()
    print X                      # wmieszane repr


C:\python\examples> python testmixin.py
<Instance of Sub, address 135423340:
         name data2=jajka
         name data3=42
         name data1=mielonka
>


>>> from mytools import Lister
>>> class x(Lister):
...     pass
...
>>> t = x()
>>> t.a = 1; t.b = 2; t.c = 3
>>> t
<Instance of x, address 7797696:
         name b=2
         name a=1
         name c=3
>


*** Strona 186-187 ***************************************************************

def factory(aClass, *args):                 # krotka varargs
    return apply(aClass, args)              # wywoanie aClass

class Mielonka:
    def doit(self, message):
        print message

class Osoba:
    def __init__(self, nazwa, praca):
         self.nazwa = nazwa
         self.praca = praca

object1 = factory(Mielonka)                 # utworzenie Mielonka
object2 = factory(Osoba, "Guido", "guru")   # utworzenie Osoba

def factory(aClass, *args, **kwargs):       # sownik kwargs
    return apply(aClass, args, kwargs)      # wywoanie aClass


*** Strona 187-188 ***************************************************************

class Mielonka:
    def doit(self, komunikat):
        print komunikat

object1 = Mielonka()
x = object1.doit               # obiekt metody zwizanej 
x('hello world')               # wprowadzono egzemplarz

t = Mielonka.doit              # obiekt metody niezwizanej 
t(object1, 'howdy')            # przekazanie egzemplarza


*** Strona 189 *******************************************************************

# plik docstr.py

"Ja jestem: docstr.__doc__"

class mielonka:
    "Ja jestem: mielonka.__doc__ albo docstr.mielonka.__doc__"

    def method(self, arg):
        "Ja jestem: mielonka.method.__doc__ albo self.method.__doc__"
        pass

def func(args):
    "Ja jestem: docstr.func.__doc__"
    pass


>>> import docstr
>>> docstr.__doc__
'Ja jestem: docstr.__doc__'

>>> docstr.mielonka.__doc__
'Ja jestem: mielonka.__doc__ albo docstr.mielonka.__doc__'

>>> docstr.mielonka.method.__doc__
'Ja jestem: mielonka.method.__doc__ albo self.method.__doc__'

>>> docstr.func.__doc__
'Ja jestem: docstr.func.__doc__'


*** Strona 191 *******************************************************************

>>> class X:
...     a = 1      # atrybut klasy
...
>>> I = X()
>>> I.a            # odziedziczony przez egzemplarz
1
>>> X.a
1

>>> X.a = 2        # moe zmieni co wicej ni X
>>> I.a            # I zmienia si rwnie
2
>>> J = X()        # J dziedziczy z wartoci X w fazie dziaania programu 
>>> J.a            # (ale przypisanie do J.a zmienia a w J, nie w X lub w I)
2


class X: pass                # tworzenie kilku przestrzeni nazw atrybutu
class Y: pass

X.a = 1                      # uycie atrybutw klasy jako zmiennych
X.b = 2                      # nie mona nigdzie znale egzemplarzy 
X.c = 3
Y.a = X.a + X.b + X.c

for X.i in range(Y.a): print X.i     # wydruk 0..5


>>> class Record: pass
...
>>> X = Record()
>>> X.name = 'bob'
>>> X.job = 'Robiacy pizze'


*** Strona 192-194 ***************************************************************

class Lister:
    def __repr__(self): ...
    def other(self): ...

class Super:
    def __repr__(self): ...
    def other(self): ...

class Sub(Super, Lister):        # podnosi __repr__ z Super wpisawszy j jako pierwsz
    other = Lister.other         # ale wyranie podnosi wersj other z Lister
    def __init__(self):
         ...


class Mielonka:
    numInstances = 0
    def __init__(self):
        Mielonka.numInstances = Mielonka.numInstances + 1
    def printNumInstances():
        print "Liczba utworzonych egzemplarzy: ", Mielonka.numInstances

>>> from mielonka import *
>>> a = Mielonka()
>>> b = Mielonka()
>>> c = Mielonka()
>>> Mielonka.printNumInstances()
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: unbound method must be called with class instance 1st argument


def printNumInstances():
    print "Liczba utworzonych egzemplarzy: ", Mielonka.numInstances

class Mielonka
    numInstances = 0
    def __init__(self):
         Mielonka.numInstances = Mielonka.numInstances + 1

>>> import mielonka
>>> a = mielonka.Mielonka()
>>> b = mielonka.Mielonka()
>>> c = mielonka.Mielonka()
>>> mielonka.printNumInstances()
Liczba utworzonych egzemplarzy:  3


class Mielonka:
    numInstances = 0
    def __init__(self):
        Mielonka.numInstances = Mielonka.numInstances + 1
    def printNumInstances(self):
        print "Liczba utworzonych egzemplarzy: ", Mielonka.numInstances

>>> from mielonka import Mielonka
>>> a, b, c = Mielonka(), Mielonka(), Mielonka()
>>> a.printNumInstances()
Liczba utworzonych egzemplarzy: 3
>>> b.printNumInstances()
Liczba utworzonych egzemplarzy: 3
>>> Mielonka().printNumInstances()
Liczba utworzonych egzemplarzy: 4


*** Strona 194-195 ***************************************************************

# plik nester.py

def generate():
    class Mielonka:
        count = 1
        def method(self):         # nazwa Mielonka niewidoczna:
            print Mielonka.count  # nie lokalna (def), globalna (modu), 
                                     wbudowana
    return Mielonka()

generate().method()

C:\python\examples> python nester.py
Traceback (innermost last):
  File "nester.py", line 8, in ?
    generate().method()
  File "nester.py", line 5, in method
    print Mielonka.count      # nie lokalna (def), globalna (modu), wbudowana
NameError: Mielonka


def generate():
    global Mielonka                 # wymusza zakres moduu dla Mielonka 
    class Mielonka:
        count = 1
        def method(self):
            print Mielonka.count    # dziaa: w globalnej (doczony modu)
    return Mielonka()

generate().method()                 # drukuje 1


def generate():
    return Mielonka()

class Mielonka:                 # definicja na najwyszym poziomie moduu 
    count = 1
    def method(self):
        print Mielonka.count    # dziaa: w globalnej (doczony modu)

generate().method()


def generate():
    class Mielonka:
        count = 1
        def method(self):
            print self.__class__.count # dziaa: kwalifikuje dla uzyskania klasy
    return Mielonka()

generate().method()


def generate():
    class Mielonka:
        count = 1
        fillin = [None]
        def method(self, klass=fillin):  # zachowanie z otaczajcego zakresu
            print klass[0].count         # dziaa: warto domylna wczona
    Mielonka.fillin[0] = Mielonka
    return Mielonka()

generate().method()


***kod do wicze znajduje si w katalogu "rozwiazania"***