Skip to content

Instantly share code, notes, and snippets.

@atemate
Last active June 4, 2024 16:41

Revisions

  1. @atemate-dh atemate-dh revised this gist Jun 4, 2024. 1 changed file with 17 additions and 0 deletions.
    17 changes: 17 additions & 0 deletions fspath.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    ```py
    >>> from os import PathLike
    >>> class MyPath(PathLike):
    ... def __init__(self, prefix, path):
    ... self._prefix = prefix
    ... self._path = path
    ...
    ... def __fspath__(self):
    ... return self._prefix + self._path
    ...
    >>>
    >>> from pathlib import Path
    >>> os.fspath(Path("test.txt"))
    'test.txt'
    >>> os.fspath(MyPath("https://", "test.txt"))
    'https://test.txt'
    ```
  2. @atemate-dh atemate-dh revised this gist Jun 4, 2024. 1 changed file with 23 additions and 0 deletions.
    23 changes: 23 additions & 0 deletions py_oop.md
    Original file line number Diff line number Diff line change
    @@ -58,3 +58,26 @@ Traceback (most recent call last):
    d = Dog()
    TypeError: Can't instantiate abstract class Dog with abstract method _say
    ```

    Often, instead of `@abc.abstractmethod` we're throwing an exception `raise NotImplementedError("implement me")` in the abstract method:

    ```py
    >>> class Animal:
    ... def _say(self):
    ... raise NotImplementedError("_say()")
    ... def speak(self):
    ... return f"I am an animal that says '{self._say()}'"
    ...
    ... class Cat(Animal):
    ... def _say(self):
    ... return "meow"
    ...
    ... class Dog(Animal):
    ... def _say(self):
    ... return "woof!"
    ...
    >>> Animal().speak()
    Traceback (most recent call last):
    ...
    NotImplementedError: _say()
    ```
  3. @atemate-dh atemate-dh created this gist Jun 4, 2024.
    60 changes: 60 additions & 0 deletions py_oop.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    Normal "minimal" usage
    ```py
    >>> class Animal:
    ... def _say(self):
    ... pass
    ... def speak(self):
    ... return f"I am an animal that says '{self._say()}'"
    ...
    >>> class Cat(Animal):
    ... def _say(self):
    ... return "meow"
    ...
    >>> class Dog(Animal):
    ... def _say(self):
    ... return "woof!"
    ...
    >>> d = Dog()
    >>> d.speak()
    "I am an animal that says 'woof!'"
    >>> c = Cat()
    >>> c.speak()
    "I am an animal that says 'meow'"
    ```

    So we're having a common abstraction `Animal` with some common functionality `speak()`, which internally uses an "abstract" method `_say()` that defines specific narrow functionality of a child concrete class (`Dog` and `Cat`).

    From the OOP high-level perspective, `Animal` is an abstract class, it's its _function_ that it serves to its children classes.

    Normally, abstract classes should not be instantiated (i.e. there can't exist an "animal", but only a "dog" or a "cat") as the program doesn't have enough information about how the instances should behave (i.e. what should `_say()` an animal, meow or bark?).

    However, Python does not restrict us from doing so:
    ```py
    >>> a.get_sentence()
    "I am an animal that says 'None'"
    ```

    So usually we're creating abstract classes using the library `abc`:
    ```py
    >>> class Animal(abc.ABC):
    ... @abc.abstractmethod
    ... def _say(self):
    ... pass
    ... def get_sentence(self):
    ... return f"I am an animal that says '{self._say()}'"
    ...
    >>> a = Animal()
    Traceback (most recent call last):
    Cell In[20], line 1
    a = Animal()
    TypeError: Can't instantiate abstract class Animal with abstract method _say

    >>> class Dog(Animal):
    ... pass
    ...
    >>> d = Dog()
    Traceback (most recent call last):
    Cell In[22], line 1
    d = Dog()
    TypeError: Can't instantiate abstract class Dog with abstract method _say
    ```