03. Обектно-ориентирано програмиране

03. Обектно-ориентирано програмиране

03. Обектно-ориентирано програмиране

12 март 2014

OOP

Обектно-ориентирано програмиране

Преговор, философски

  1. Абстракция
  2. Енкапсулация
  3. Модулярност

Преговор, по същество

  1. Всичко е обект
  2. Отворени обекти
  3. Отворени класове

Примерен клас Vector

class Vector:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

spam = Vector(1.0, 2.0, 3.0)
print(spam.x)
  1. Конструктура се казва __init__
  2. Първия аргумент на метода е инстанцията, върху която се извиква
  3. Атрибутите ("член-променливите") не е задължително да се декларират (класовете са отворени)
  4. Инстанцира се с оператор ()

Примерен клас Vector (2)

class Vector:
    def __init__(self, x, y, z): ...

    def length(self):
        return (self.x * self.x + self.y * self.y + self.z * self.z) ** 0.5

    spam = Vector(1.0, 2.0, 3.0)
    print(spam.length())
  1. В методите атрибутите се достъпват през self
  2. Методите се извикват с обект.име_на_метод()

Примерен клас Vector (3)

class Vector:
    def __init__(self, x, y, z): ...

    def _coords(self):
        return (self.x, self.y, self.z)

    def length(self):
        return sum(_ ** 2 for _ in self._coords()) ** 0.5
  1. _coords е protected метод
  2. Отново, методите се извикват върху self
  3. _ е валидно име за променлива

Извикване през класа

v1 = Vector(1.0, 2.0, 3.0)
v2 = Vector(4.0, 5.0, 6.0)
v3 = Vector(7.0, 8.0, 9.0)

print(Vector.length(v1))
print(Vector.length(v2))
print(list(map(Vector.length, [v1, v2, v3])))

Vector (4)

class Vector:
    def __init__(self, x, y, z): ...

    def length(self): ...

    def normalize(self):
        length = self.length()
        self.x /= length
        self.y /= length
        self.z /= length

Vector (5)

class Vector:
    def __init__(self, x, y, z): ...

    def length(self): ...

    def normalize(self):
        length = self.length()
        return Vector(self.x / length,
                      self.y / length, self.z / length)

normalize vs normalized

class Vector:
    ...

    def normalize(self):
        length = self.length()
        self.x /= length
        self.y /= length
        self.z /= length

    def normalized(self):
        return Vector(self.x / self.length(), self.y / self.length(),
                      self.z / self.length())

Сравняване на обекти

Аритметични оператори

Можете да предефинирате аритметичните оператори за вашите типове.

Преобразуване до стандартни типове

Има методи, които може да предефинирате, за преобразования от вашия клас към стандартен тип

Обекти, които могат да бъдат извиквани като функции

Можете да предефинирате оператора две скоби ().

class Stamp:
    def __init__(self, name): self.name = name
    def __call__(self, something):
        print("{0} was stamped by {1}".format(something, self.name))

>>> stamp = Stamp("The government")
>>> stamp("That thing there")
That thing there was stamped by The government

Статични методи

Можете да "декорирате" методи, така че те да станат статични -- т.е. да нямат нужда от инстанция

class GoatSimulator:
    goats = []

    @staticmethod
    def register(name):
        GoatSimulator.goats.append(name)
        print(len(GoatSimulator.goats), " goats are registered now")

>>> GoatSimulator.register("Pip the Happy Goat")
1 goats are registered now
>>> GoatSimulator.register("George the Gutsy Goat")
2 goats are registered now

Класови методи

Можете да използвате и @classmethod, за да получите класа от който е извикан метода като първи аргумент

class Something:
    @classmethod
    def greet(cls, someone):
        print(someone, "was greeted from", cls)

>>> Something.greet("Stefan")
Stefan was greeted from <class '__main__.Something'>

Property методи

Декораторът @property може се използва за да накарате някой метод да се преструва на property

class Goat:
    def __init__(self, name, trait):
        self.name = name
        self.trait = trait

    @property
    def description(self):
        return "{} the {} goat".format(self.name, self.trait)

>>> g = Goat("George", "Gutsy")
>>> g.description
'George the Gutsy goat'

Property методи (2)

Property методи (3)

class Color:
    def __init__(self, rgba):
        self._rgba = tuple(rgba)

    @property
    def rgba(self):
        return self._rgba

    @rgba.setter
    def rgba(self, value):
        self._rgba = tuple(value)

>>> red = Color([255,0,0])
>>> red.rgba
(255, 0, 0)
>>> red.rgba = [127,0,0]
>>> red.rgba
(127, 0, 0)

mutable срещу immutable

Vector (6)

def addition(a, b):
    return Vector(a.x + b.x, a.y + b.y, a.z + b.z)

class Vector:
    def __init__(self, x, y, z): ...

    __add__ = addition

print(Vector(1.0, 2.0, 3.0) + Vector(4.0, 5.0, 6.0))
  1. Функциите са първокласни обекти
  2. Методите са атрибути на класа
  3. Класовете са динамични
  4. Ето защо self е явен

Въпроси?