<jupyter_start><jupyter_text>![](data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgQEhUQBxESFhEXERASEBAPFhIVGBgdFRUXFhUWFxQYHTQgJBolGxgXITIhJSkrLi4vFyAzODMsNygtLisBCgoKDg0OGxAQGyslICUrLTcwNzc3LTEwMi0rNysvLS03KzgtLS0tLS0tLzYtNS03NSsrLS01LS0tLTcrLSsrNv/AABEIAOEA4QMBIgACEQEDEQH/xAAbAAEAAwEBAQEAAAAAAAAAAAAABAUGAwEHAv/EAEAQAAICAQMDAgIHBQQJBQAAAAABAgMEBRESBhMhMUFRYRQVIlJxgaEHMjORsSNCYsFyc5KTorLR4fAWNENVg//EABoBAQADAQEBAAAAAAAAAAAAAAABAgUEAwb/xAAmEQEAAgICAQIGAwAAAAAAAAAAAQIDEQQFIRJREzEyQVJxFCIz/9oADAMBAAIRAxEAPwD7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3BF1G6UK5Sj67ePz8FMmSMdJtP2TEbnSRuj3dGXx8XMuTlW9/PvJo7fVWf8AH/iZk17PLaPVXFMw6JwVidTaGi3Q5IzNOBmy34P0bi95P1R+/qrP+K/2mTHZZpjcYZR8Gv5Q0fJDdGZrwMyTag/R7P7T+R0+qtQ+K/2mI7LNMbjDKfg0/OGickEzMRwc1uUYPzHbf7T91uv0PVbn0P7fLb4S8p/mRHbWjzfHMR7n8eJ+m0TLTgi4GZC2O8fD918CUa2PJXJWLVnxLnmJidSAAugAAAAAAAAAAAAAAAAAAAAACBrP8KX5f1RPIGtfwZfl/V<KEY>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9k=)  Python Object-Oriented Programming (OOP)_<NAME>_  Metody specjalne (magiczne, dundery)![](https://amir.rachum.com/images/posts/butwait1.png)  Metody specjalne >  Przeciążanie operatorów> **Przeciążanie operatorów** ([ang](https://pl.wikipedia.org/wiki/J%C4%99zyk_angielski). *operator overloading*) lub **przeładowanie operatorów** – polega na tym, że [operator](https://pl.wikipedia.org/wiki/Operator_(programowanie)) może mieć różne implementacje w zależności od typów użytych argumentów (operandów).> > Przeciążanie operatorów to typowy tzw. [lukier składniowy](https://pl.wikipedia.org/wiki/Lukier_sk%C5%82adniowy) (cecha składni języka, którą można wyeliminować przez proste przekształcenia składniowe, istniejąca jedynie dla wygody programisty). Potencjalnie znacznie poprawia czytelność kodu i umożliwia zdefiniowanie większej części [biblioteki standardowej](https://pl.wikipedia.org/wiki/Biblioteka_programistyczna) na poziomie języka, bez uciekania się do trików. Z drugiej strony, ta technika programistyczna może spowodować powstawanie niejasnych konstrukcji, gdzie operatory wykonują kompletnie różne czynności w zależności od ich operandów.> > Na przykład Pythonie, jeżeli:<jupyter_code>a = 1<jupyter_output><empty_output><jupyter_text>> To wyrażenie:<jupyter_code>a * 2<jupyter_output><empty_output><jupyter_text>> Normalnie oznacza przemnożenie liczby o `2`.> > Ale, jeśli:<jupyter_code>a = 'a'<jupyter_output><empty_output><jupyter_text>> To:<jupyter_code>a * 2<jupyter_output><empty_output><jupyter_text>> Oznacza to podwojenie `'a'`.> > A jak interpretować ten fragment gdy `a` jest jeszcze czymś innym?> > Z tego powodu zalecane jest, aby przeciążać tylko te operatory, których znaczenia łatwo się domyślić, gdyż mają swój odpowiednik w matematyce, fizyce itp. Klasy umożliwiają przeładowywanie (przeciążanie) operatorów (podobnie jak w C++). Jest to możliwe dzięki specjalnym metodom, które można zaimplementować w klasie. Poniżej przykład klasy `Special`, w której zdefiniowano kilka metod specjalnych.<jupyter_code>class Special:
    def __init__(self, *args, **kwargs):
        pass
        # konstruktor

    def __del__(self):
        pass
        # Destruktor – rzadko wykorzystywany

    def __str__(self):
        pass
        # Reprezentacja znakowa; wywoływana przez print i str

    def __repr__(self):
        pass
        # Reprezentacja znakowa; wywoływana przez repr
        # eval(repr(a)) powinno być równe a

    def __getitem__(self, i):
        pass
        # Indeksacja dla obiektu: b = a[i]

    def __setitem__(self, i, v):
        pass
        # Przypisanie z wykorzystaniem indeksacji: a[i] = v

    def __len__(self):
        pass
        # Wywoływane przez len(a);  Funkcja powinna zwrócić
        # długość obiektu (o ile ma to uzasadnienie)

    def __eq__(self, x):
        pass
        # Test self == x; zwraca True lub False

    def __add__(self, b):
        pass
        # Definiuje self + b

    def __sub__(self, b):
        pass
        # Definiuje self – b

    def __mul__(self, b):
        pass
        # Definiuje self * b

    def __div__(self, b):
        pass
        # Definiuje self / b

    def __pow__(self, b):
        pass
        # Definiuje self ** b<jupyter_output><empty_output><jupyter_text>Lista metod specjalnychW poprzednim podrozdziale zostało to już wstępnie przedstawione, tutaj przyjrzymy się metodom specjalnym w Pythonie bardziej szczegółowo.Metody specjalne są metodami, których nazwy zaczynają i kończą się podwójnym podkreśleniem `__`. Najważniejszą, najczęściej wykorzystywaną metodą specjalną jest `__init__`. Metody te są specjalne, ponieważ Python w specjalny sposób je wywołuje. Zestawienie popularnych metod przedstawione jest poniżej.| Metoda      | Opis                                                                                                         ||-------------|--------------------------------------------------------------------------------------------------------------|| `__init__`    | Inicjalizator, uruchamiany od razu po utworzeniu instancji                                                   || `__del__`     | Finalizator, uruchamiany tuż przed zniszczeniem instancji                                                    || `__repr__`    | "Oficjalna" reprezentacja tekstowa obiektu, format najlepiej ``; zwraca `str` || `__str__`     | "Nieoficjalna" reprezentacja tekstowa, czytelna dla użytkowników; zwraca `str`                                 || `__bytes__`   | Reprezentacja bajtowa; zwraca `bytes`                                                                          || `__format__`  | Reprezentacja tekstowa używana przy poleceniach formatujących (`str.format`, `format()`, `f""`); zwraca `str`        || `__lt__`      | Operator `<` (*lower than*)                                                                                      || `__le__`      | Operator `<=` (*lower or equal*)                                                                                 || `__eq__`      | Operator `==` (*equal*)                                                                                          || `__ne__`      | Operator `!=` (*not equal*)                                                                                      || `__gt__`      | Operator `>` (*greater than*)                                                                                    || `__ge__`      | Operator `>=` (*greater or equal*)                                                                               || `__bool__`    | Metoda używana do sprawdzania wartości prawdy dla instancji, również przy wywołaniu `bool(instancja)`          || `__abs__`     | Wywoływana przez `abs(instancja)`, służy do obliczania modułu wartości                                         || `__add__`     | Operator `+` (*add*)                                                                                             || `__sub__`     | Operator `-` (*subtract*)                                                                                        || `__mul__`     | Operator `*` (*multiply*)                                                                                        || `__truediv__` | Operator `/` (*divide*)                                                                                          || `__neg__`     | Operator negacji, `-instancja`                                                                                 |  Zadanie - implementacja wektoraZaimplementuj klasę `Vector`, służącą do reprezentacji [wektorów matematycznych (dwuwymiarowych)](https://pl.wikipedia.org/wiki/WektorPodstawowe_w%C5%82asno%C5%9Bci). Klasa przyjmuje dwie wartości: `x` i `y`. Jeśli chodzi o metody, ogranicz się do:dodawania i odejmowania wektorów (`__add__`, `__sub__` - spróbuj zaimplementować odejmowanie przy pomocy kolejnej metody specjalnej `__neg__`),moduł (długość; `__abs__`), wykorzystaj funkcję `math.hypot`,mnożenie przez skalar (`__mul__`),dzielenie przez skalar (`__truediv__`),reprezentacja tekstowa (`__repr__` oraz `__str__`).Gdy nie znasz argumentów, które muszą przyjąć metody, posłuż się `dokumentacją`. >  `math.hypot(*coordinates)`> Zwraca normę euklidesową, `sqrt(suma(x**2 for x in coordinates))`. Jest to długość wektora od początku do punktu określonego przez współrzędne.> > W przypadku punktu dwuwymiarowego `(x, y)` jest to równoważne obliczeniu przeciwprostokątnej trójkąta prostokątnego za pomocą twierdzenia Pitagorasa, `sqrt(x*x + y*y)`.> > *Zmieniono w wersji 3.8:* Dodano obsługę punktów n-wymiarowych. Wcześniej obsługiwana była tylko wersja dwuwymiarowa. Przetestuj działanie swojej klasy:```python>>> v = Vector(4, 7)>>> v + Vector(-4, 7)Vector(0, 14)>>> v * 3Vector(12, 21)>>> abs(v)8.06225774829855```  Rozwiązanie - implementacja wektora<jupyter_code>import math


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

    def __neg__(self):
        return Vector(-self.x, -self.y)

    def __add__(self, v2):
        return Vector(self.x + v2.x, self.y + v2.y)

    def __sub__(self, v2):
        return Vector(self.x - v2.x, self.y - v2.y)
        # alternatywnie:
        # return self + (-v2)

    def __abs__(self):
        return math.hypot(self.x, self.y)

    def __mul__(self, scalar):
        return Vector(scalar * self.x, scalar * self.y)

    def __truediv__(self, scalar):
        return Vector(self.x / scalar, self.y / scalar)

    def __repr__(self):
        return "<Vector({}, {})>".format(self.x, self.y)

    def __str__(self):
        return "Vector({}, {})".format(self.x, self.y)<jupyter_output><empty_output><jupyter_text>Testowanie:<jupyter_code>v1 = Vector(1, 2)
v2 = Vector(2, 1)
v1 + v2
v1 - v2
abs(v1), abs(v2)
v1 * 3
v1 / 3
print(v1)
str(v1)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10209424083769633, 'fraction_numerical': 0.015203383004430126, 'mean_word_length': 2.446564885496183, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 68, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 56, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '53788', 'license': 'CC0-1.0', 'n_tokens_mistral': 3549, 'n_tokens_neox': 3560, 'n_words': 698, 'path': 'Python/.ipynb_checkpoints/05 Python OOP - metody specjalne-checkpoint.ipynb', 'repo_name': 'miklesz/codebrainers', 'size': '13575'}