Python: Magic Methods, Context Manager

Magic methods

__new__: Called to create a new instance of class cls. What is happening at the moment of class creation (like checking if there should be only one instance of such class)
__init__: Called after the instance has been created (by __new__())
__del__: better not to change:)
__str__: Called by str(object) and the built-in functions format() and print() to compute the “informal” or a nicely printable string representation of an object

__hash__: Called by built-in function hash() and for operations on members of hashed collections including set, frozenset, and dict. hash() should return an integer. – (what will be used as a key in the dictionary)
__eq__: x==y calls x.eq(y)

__getattr__: Called when the default attribute access fails with an AttributeError – when the attribute is not found
__getattribute__: Called unconditionally to implement attribute accesses for instances of the class

__setattr__: Called when an attribute assignment is attempted
__delattr__: Like setattr() but for attribute deletion instead of assignment.

__call__: Called when the instance is “called” as a function; (could also be used as a decorator for the function)

__add__; __sub__; __and__ etc : These methods are called to implement the binary arithmetic operations

__getitem__(self, key): Called to implement evaluation of self[key]
___setitem__(self, key, value): Called to implement assignment to self[key].


__iter__: This method is called when an iterator is required for a container. Must always return an iterator
__next__: Return the next item from the container.

Context Manager

Context manager = “with” … as :

__enter__: Enter the runtime context and return either this object or another object related to the runtime context. (operator “as)
__exit__: Exit the runtime context and return a Boolean flag indicating if any exception that occurred should be suppressed.
class open – from lower “o”, because it is a context manager and not a Class

with open("file.txt) as f:
    file_read =

You don’t need to close the file, because the context manager “open” is configured to close it at the end.

A descriptor is an object attribute with “binding behavior”

descr.get(self, obj, type=None) -> value
descr.set(self, obj, value) -> None
descr.delete(self, obj) -> None

This image has an empty alt attribute; its file name is Screen-Shot-2019-12-19-at-9.28.21-PM-699x1024.png
Entire code to copy
"""Magic Methods"""

class Robot:
    def __init__(self, name, model, year): = name
        self.model = model
        self.year = year

    def __str__(self):
        return f"{} - {self.model}, {self.year}"
    def __hash__(self):
        return hash(self.model)
    def __eq__(self, obj):
        return self.year == obj.year
    def __getattr__(self, item):
        return "Nothing"
    def __getattribute__(self, item):
        print(f"Using __getattribute__::: Logging something with . {item} counts")
        return object.__getattribute__(self, item)
    def __setattr__(self, key, value):
        print(f"Using __setattr__::: I am going to add {value} into {key}, but can just skip it")
        object.__setattr__(self, key, value)
    def __delattr__(self, item):
        value = getattr(self, item)
        print(f"Using __delattr__::: No way I delete {value}")
        object.__delattr__(self, item)

    def __getitem__(self, item):
        print("Here is your item")

    def __setitem__(self, key, value):
        print("Here is your item")

robot1 = Robot("Name_Robot1", "Model_Robot1", 1988)


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        result = self.current ** 2
        self.current += 1
        return result

for num in MyIterator(1,5):

class Mylist:
    def __init__(self, orig_list=None):
        self.container = orig_list or []

    def __str__(self):
        return self.container.__str__()

    def __getitem__(self, index):
        return self.container[index-1]

    def __setitem__(self, index, value):
        self.container[index] = value

numbers = Mylist([1,2,3,4,5])
numbers[4] = "KOKOKO"

"""Context Manager"""

class open_file_time:
    def __init__(self, filename, mode):
        self.file = open(filename, mode)

    def __enter__(self):
        return self.file

    def __exit__(self, *args):

with open_file_time("file.txt", 'w') as f:
    f.write("this this a line\n")

with open_file_time("file.txt", 'r') as f: