super


In [195]:
class A(object):
    def __init__(self, **kwargs):
        print('A.__init__ with {}'.format(kwargs))
        super(A, self).__init__()
class B(A):
    def __init__(self, **kwargs):
        print('B.__init__ with {}'.format(kwargs))
        super(B, self).__init__(**kwargs)
class C(A):
    def __init__(self, **kwargs):
        print('C.__init__ with {}'.format(kwargs))
        super(C, self).__init__(**kwargs)
class D(B, C):
    def __init__(self):
        print('D.__init__')
        super(D, self).__init__(a=1, b=2, x=3)

In [196]:
print(D.mro())
D()


[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
D.__init__
B.__init__ with {'a': 1, 'x': 3, 'b': 2}
C.__init__ with {'a': 1, 'x': 3, 'b': 2}
A.__init__ with {'a': 1, 'x': 3, 'b': 2}
Out[196]:
<__main__.D at 0x102c28c10>

In [31]:
class A(object):
    def __init__(self, a):
        self.a = a

class B(A):
    def __init__(self, b, **kw):
        self.b = b
        super(B, self).__init__(**kw)

class C(A):
    def __init__(self, c, **kw):
        self.c = c
        super(C, self).__init__(**kw)

class D(B, C):
    def __init__(self, a, b, c):
        super(D, self).__init__(a=a, b=b, c=c)

In [32]:
obj = D(1,2,3)

In [197]:
obj.a, obj.b, obj.c


Out[197]:
(1, 2, 3)

In [68]:
class First(object):
    def __init__(self):
        print "first"

class Second(First):
    def __init__(self):
        print "second before super"
        super(Second, self).__init__()
        print "second after super"

class Third(First):
    def __init__(self):
        print "third before super"
        super(Third, self).__init__()
        print "third after super"

class Fourth(Second, Third):
    def __init__(self):
        print "fourth before super"
        super(Fourth, self).__init__()
        print "that's it"

In [69]:
Fourth()


fourth before super
second before super
third before super
first
third after super
second after super
that's it
Out[69]:
<__main__.Fourth at 0x102be9910>

In [75]:
class First(object):
    def __init__(self):
        print "first"

class Second(First):
    def __init__(self):
        print "second before super"
        super(Second, self).__init__(a=2)
        print "second after super"

class Third(First):
    def __init__(self, a):
        print "third before super"
        super(Third, self).__init__()
        print "third after super"

class Fourth(Second, Third):
    def __init__(self):
        print "fourth before super"
        super(Fourth, self).__init__()
        print "that's it"

In [76]:
Fourth()


fourth before super
second before super
third before super
first
third after super
second after super
that's it
Out[76]:
<__main__.Fourth at 0x102be9a90>

In [77]:
Second()


second before super
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-77-e8b862a7f38b> in <module>()
----> 1 Second()

<ipython-input-75-3b05ad4e2c8b> in __init__(self)
      6     def __init__(self):
      7         print "second before super"
----> 8         super(Second, self).__init__(a=2)
      9         print "second after super"
     10 

TypeError: __init__() got an unexpected keyword argument 'a'

Metody wirtualne?


In [81]:
class A():
    def suma(self, a, b):
        return a + b
    
class AzMnozeniem(A):
    def mnozenie(self, a, b):
        return a * b

In [82]:
k = AzMnozeniem()

In [83]:
k.mnozenie(3, 4)


Out[83]:
12

In [84]:
k.suma(3, 4)


Out[84]:
7

Przeciążanie operatorów


In [88]:
class A(object):
    def __init__(self, a):
        self.a = a
    
    def __add__(self, other):
        self.a += other.a
        return self

In [90]:
(A(4) + A(5)).a


Out[90]:
9

object.__lt__(self, other) object.__le__(self, other) object.__eq__(self, other) object.__ne__(self, other) object.__gt__(self, other) object.__ge__(self, other) object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__floordiv__(self, other) object.__mod__(self, other) object.__divmod__(self, other) object.__pow__(self, other[, modulo]) object.__lshift__(self, other) object.__rshift__(self, other) object.__and__(self, other) object.__xor__(self, other) object.__or__(self, other)

Klasy abstrakcyjne


In [93]:
import abc

class Person():
    __metaclass__ = abc.ABCMeta

    def __init__(self, name):
        self.name = name

    @abc.abstractmethod
    def say_hello(self):
        pass

class Programmer(Person):
    def __init__(self, name, language):
        Person.__init__(self, name)
        self.language = language

    def say_hello(self):
        print('Hello! I\'m %s and I write in %s.' % (self.name, self.language))

In [98]:
p = Person(name="Duck")
p


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-98-fb3ac259b820> in <module>()
----> 1 p = Person(name="Duck")
      2 p

TypeError: Can't instantiate abstract class Person with abstract methods say_hello

In [97]:
p = Programmer(name="Duck", language="Duck++")
p


Out[97]:
<__main__.Programmer at 0x102c1c490>

In [99]:
p.say_hello()


Hello! I'm Duck and I write in Duck++.

Atrybuty


In [105]:
class A(object):
    b = "0.001"
    def __init__(self, a):
        self.a = a

In [106]:
A.b


Out[106]:
'0.001'

In [107]:
A.a


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-107-c22b74faba98> in <module>()
----> 1 A.a

AttributeError: type object 'A' has no attribute 'a'

In [108]:
A(234).a


Out[108]:
234

Ciekawostki


In [111]:
class A():
    j = 0
    for i in range(10):
        j += i

In [112]:
A.j


Out[112]:
45

Prędkość


In [146]:
import math
import random
class Pole(object):
    def __init__(self, r=2.):
        self.r = r
    def oblicz(self):
        return math.pi * (self.r**2)

In [147]:
n = 1000
def get_mean_cls(n=n):
    return sum([Pole(random.random()).oblicz() for i in range(n)])/float(n)
def get_mean(n=n):
    return sum([math.pi * (random.random()**2) for r in range(n)])/float(n)

In [152]:
%timeit get_mean_cls()


1000 loops, best of 3: 920 µs per loop

In [153]:
%timeit get_mean()


1000 loops, best of 3: 286 µs per loop

Property


In [161]:
class Kaczka(object):
    def __init__(self, dl_skrzydla):
        self.dl_skrzydla = dl_skrzydla
    
    def plyn(self):
        print "Chlup chlup"

In [162]:
k = Kaczka(124)
k.plyn()
k.dl_skrzydla


Chlup chlup
Out[162]:
124

In [165]:
class Kaczuszka(Kaczka):
    def __init__(self, dl_skrzydla):
        self._dl_skrzydla = dl_skrzydla
    
    @property
    def dl_skrzydla(self):
        return self._dl_skrzydla / 2.
    
    @dl_skrzydla.setter
    def dl_skrzydla(self, value):
        self._dl_skrzydla = value

In [184]:
k = Kaczuszka(124)
k.plyn()
k.dl_skrzydla


Chlup chlup
Out[184]:
62.0

In [188]:
k.dl_skrzydla = 100
k.dl_skrzydla


Out[188]:
50.0

In [189]:
k.dl_skrzydla += 50

In [190]:
k.dl_skrzydla


Out[190]:
50.0

Zadanie

1 . Stworz klasę koło w którą inicjalizuje się promieniem.
Klasa ta powinna mieć metody obliczające:

  • obwód
  • pole
  • metodę statyczną zmieniającą kąt na radiany
  • dodatkowy konstruktor tworzący klasę ze średnicy


2 . Napisz klasę opona która również inicjalizujesz promieniem.
Obwód opony jest 1.25 razy większy od obowodu koła.
3 . Do liczenia pola w klasie koło wykorzystaj metodę licząca obwód. (Przepisy to regulują nic nie możesz z tym zrobić, wiem to nieoptymalne, ale mus to mus)
4 . Co się stało z klasa opony? Czy jej pole liczone jest poprawnie? Zabezpiecz kod przed tym!
5 . Nowy rząd dużo ostatnio mąci... mówi, że nie wolno nam zapisywać atrybutu "promień" w kole, musimy zapisywać średnice, spraw aby kod klasy opona nadal działał

Postaraj się, żeby kod był ładny, napisz docstringi, wersje ...