Подробное описание: https://docs.python.org/3/reference/datamodel.html#special-method-names
__init__(self, ...)
- Инициализатор класса.__del__(self)
- "Деструктор" класса.Пример:
from os.path import join
class FileObject:
def __init__(self, filepath, filename):
self.file = open(join(filepath, filename), 'r+')
def __del__(self):
self.file.close()
del self.file
__cmp(self, other)__
- Метод должен возвращать отрицательное число если self < other
, нуль в случае когда self == other
, и поожительное число когда self > other
.__eq(self, other)__
- ==
__neq(self, other)__
- !=
__lt(self, other)__
- <
__gt(self, other)__
- >
__le(self, other)__
- <=
__ge(self, other)__
- >=
__pos__(self)
- определяет поведение для унарного плюса__neg__(self)
- определяет поведение для унарного минуса__abs__(self)
__round__(self, n), __floor__(self, n), __ceil__(self, n)
- определяют поведение при вызове стандартного метода math.round(x),...
.__add__(self, other), __sub__(self, other)
__mul__(self, other), __div__(self, other), __floordiv__(self, other), __mod__(self, other)
__lshift__(self, other), __rshift__(self, other)
__and__(self, other), __or__(self, other), __xor__(self, other)
Было
{python}
self_object + other
Стало
{python}
other + self_object
Таким образом, все эти магические методы делают то же самое, что и их обычные версии, за исключением выполнения операции с other
в качестве первого операнда и self
в качестве второго. В большинстве случаев, результат отражённой операции такой же, как её обычный эквивалент, поэтому при определении __radd__
вы можете ограничиться вызовом __add__
. Объект слева от оператора (other
в примере) не должен иметь обычной неотражённой версии этого метода. Метод self_object.__radd__
будет вызван только если в other
не определён __add__
.
Пример:
__radd__(self, other)
Все теже методы, что и в списке обычных арифметических операторов. Пример:
__iadd__(self, other)
__int__(self)
__float__(self)
__oct__(self)
Для того чтобы можно было пользоваться объектом класса как функцией, нужно определить в классе магический метод
__call__(self, [args...])
.
Объекты итераторы в питоне соответствуют протоколу итератора, то есть имеют два метода: __iter__()
и __next__()
. Метод __iter__
возвращает объект итератор, и неявно вызывается в начале цикла.
Метод __next__
возвращает следующее значение, и неявно вызывается во время каждой итерации цикла.
Данный метод кидает StopIteration
всякий раз, когда больше нет объектов, которые можно было бы вернуть.Исключение неявно ловится, для того чтобы прекратить итерирование.
Напоминание:
for x in xs:
do_something(x)
Процесс исполнения оператора for можно концептуально записать так:
it = iter(xs)
while True:
try:
x = next(it)
except StopIteration:
break
do_something(x)
Пример:
class inf_iterator:
def __init__(self):
self.counter = -1
def __iter__(self):
return self
def __next__(self):
self.counter += 1
return self.counter
it = inf_iterator()
next(it)
class counter:
def __init__(self, low, high):
self.current = low
self.high = high
def __iter__(self):
return self
def __next__(self):
if self.current > self.high:
raise StopIteration
self.current += 1
return self.current - 1
for c in counter(3, 8):
print(c)
Генераторы позволяют писать функции, которые ведут себя как итераторы, то есть, в частности, могут быть использованы в циклах.
Пример использования:
def firstn(n):
num, nums = 0, []
while num < n:
nums.append(num)
num += 1
return nums
def firstn(n):
num = 0
while num < n:
yield num
num += 1
class node:
def __init__(self, l=None, r=None, x=None):
self.key = x
self.left = l
self.right = r
def insert(root_node, x):
raise NotImplementedError
def inorder_traversal(node):
raise NotImplementedError
Реализация методов __enter__(self)
и __exit__(self, exception_type, exception_value, traceback)
позволяет использовать экземпляр класса с конструкцией with
.
Пример:
class DatabaseConnection(object):
def __enter__(self):
# make a database connection and return it
...
return self.dbconn
def __exit__(self, exc_type, exc_val, exc_tb):
# make sure the dbconnection gets closed
self.dbconn.close()
...
использование
with DatabaseConnection() as mydbconn:
# do stuff
Открыть http://mit.spbau.ru/sewiki/images/3/34/Python_2014_05.pdf со слайда 4.
Примеры:
final
class final(type):
def __init__(cls, name, bases, dct):
super(final, cls).__init__(name, bases, dct)
finals = [base.__name__ for base in bases if isinstance(base, final)]
if len(finals) > 0:
raise TypeError('Classes ' + str(finals) + ' are final')
class A(object): pass
class B(A, metaclass = final): pass
class C(object, metaclass = final): pass
class D(B, C): pass
singleton
class singleton(type):
instance = None
def __call__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = super(singleton, cls).__call__(*args, **kwargs)
return cls.instance
class Singleton(object, metaclass = singleton): pass
a = Singleton()
b = Singleton()
a is b