Вопрос Как правильно обернуть данные в Python? Нужен ли шаблон __init__
и self.
?
Как класс Иногда я хочу создать классы, которые представляют Данные, но не имеют сложной вычислительной механики внутри. Например:
class DataClass:
def __init__(self, a, b, c):
self.a = b
self.b = b
self.c = c
def sum(self):
return self.a + self.b + self.c
dc = DataClass(1,2,3)
print(dc.sum())
Мне не нравится этот код, математика a + b + c
трудна для чтения из-за self.
, а конструктор является шаблонным. Более того, я создаю этот класс всякий раз, когда замечаю, что кортеж или диктат вокруг a, b и c становится беспорядочным. В частности, кортежи выглядят некрасиво, когда возвращаемые значения изменяются в количестве или порядке, как это происходит с cv2.findContours
между версиями 3 и 4 opencv (возвращая 3 или 2 значения соответственно). Наконец, я часто копирую и вставляю шаблоны, легко допуская болезненные ошибки, как в случае с self.a = b
.
как функция Поэтому я часто делаю что-то вроде этого:
def DataFunc(a, b, c):
class Result:
def sum(self):
return a + b + c
return Result()
df = DataFunc(1,2,3)
print(df.sum())
Работает и значительно прозрачнее (imho), но также немного странно по отношению к типам, т. Е.
rf2 = ResultFunc(1,2,3)
print(type(rf) == type(rf2)) # -> False
Кроме того, элементы данных недоступны (rf.a
rf.b
и т. Д.)
Как класс с аннотатором Наконец, можно создать аннотатор для добавления конструктора:
def add_constructor(*vars):
def f(class_):
def init(self, *args, **kwargs):
unasigned = set(vars[len(args):]) - set(kwargs.keys())
if len(unasigned) > 0:
raise ValueError(f"Missing argument(s): {' '.join(unasigned)}")
for name, value in zip(vars, args):
setattr(self, name, value)
for name, value in kwargs.items():
setattr(self, name, value)
setattr(class_, '__init__', init)
return class_
return f
@add_constructor('a', 'b', 'c')
class DataAnnot:
def sum(self):
return self.a + self.b + self.c
da = DataAnnot(1,2,c=3)
print(da.sum())