Многие новичков и даже программистов Pythonic думают, что __init __ ()
это конструктор, поскольку он инициализирует значения, когда его называют, но __init __ ()
это Специальный метод который инициализирует объекты, и он немедленно вызывается, когда объект создается и инициализируется и не выделяет память. Так что это не единственный метод для конструктора.
class Foo: def __init__(self, value_a, value_b): self.a = value_a self.b = value_b foo = Foo(7, 9) # __init__ is called print(foo.a , foo.b) # 7 , 9
__new __ ()
Метод называется до __init __ ()
Деяния. Это потому, что __new __ ()
распределяет память до __init __ ()
называется.
def __new__(cls, *args, **kwargs)
Вещи, которые нужно иметь в виду о __new __ ()
:
__new __ ()
всегда вызывается до__init __ ()
Отказ- Первый аргумент – это сам класс, который передан неявно.
- Всегда возвращайте действительный объект из Новый (). Не обязательно, но это весь смысл.
__new __ ()
Управляет созданием объекта. Это означает, что в крайнем случае вы можете вернуть совершенно другой тип объекта в конце. Я дам пример в ближайшее время.
class Point(): def __new__(cls,*args,**kwargs): print("From new") print(cls) print(args) print(kwargs) # create our object and return it obj = super().__new__(cls) return obj def __init__(self, x = 0, y = 0): print("From init") self.x = x self.y = y
Выход:
>>> p2 = Point(3,4) From new(3, 4) {} From init
Мы видим, что __new __ ()
называется до __init __ ()
Когда объект инициализируется и может также увидеть, что параметр CLS
в __new __ ()
это сам класс (точка). Наконец, объект создается, вызывая __new __ ()
Способ на объекте базовый класс. В Python объект является базовым классом, из которого происходят все остальные классы. В приведенном выше примере мы сделали это, используя Super ()
Отказ
Когда использовать __в этом__() а также __новый__() ?
Вы бы видели __init __ ()
использоваться чаще, чем __new __ ()
Как нам в основном нужно инициализировать объекты, а не то, как объект контролируется, хотя мы можем использовать __new __ ()
инициализировать объекты, но это будет иметь больше смысла инициализации их в __init __ ()
Отказ
Некоторое практическое использование __new __ ()
Можно ограничить количество объектов, созданных из класса, сделать синглтон и вернуть совершенно другой объект в конце.
Ограничить количество созданных объектов
Предположим, мы хотим сделать класс Прямая точка
Для создания экземпляров для представления четырех вершин квадрата. Мы можем наследовать от нашей предыдущей точки класса (первый пример в этой статье) и использовать Новый () Для реализации этого ограничения. Вот пример ограничения класса, чтобы иметь только четыре экземпляра.
class RectPoint(Point): MAX_Inst = 4 Inst_created = 0 def __new__(cls,*args,**kwargs): if (cls.Inst_created >= cls.MAX_Inst): raise ValueError("Cannot create more objects") cls.Inst_created += 1 return super().__new__(cls)
Пробег образец.
>>> p1 = RectPoint(0,0) >>> p2 = RectPoint(1,0) >>> p3 = RectPoint(1,1) >>> p4 = RectPoint(0,1) >>> >>> p5 = RectPoint(2,2) Traceback (most recent call last): ... ValueError: Cannot create more objects
Простой синглтон
В этом вы должны быть осторожны в __init __ ()
Поскольку он называется каждый раз, когда вы «создаете» объект (т. Е. Вы делаете A ()
), хотя они возвращают один и тот же объект.
_singleton = None class Example: def __new__(cls): global _singleton if _singleton is None: _singleton = super(Example, cls).__new__(cls) return _singleton a = Example() b = Example() a is b # output: True
Возвращение полностью нового объекта
В этом примере int .__ init __ ()
будет называться, а не Пример .__ init __ ()
, как возвращенный объект не типа Пример
Но int.
.
class Example: def __new__(cls): return 3 type(Example()) # output: int
Таким образом, оба __new __ ()
и __init __ ()
Работа и функционируйте как конструктор с других языков OOP, такие как C ++, поскольку он выделяет и инициализирует объекты. Но как __init __ ()
в основном используется указанный выше. Вы можете позвонить __init __ ()
«Конструктор», поскольку мы не заботимся о распределении. Python – очень абстрагированный язык, и нам не нужно больше заботиться о памяти.
Я надеюсь, что мой пост уточняет это хорошо, и если есть какие-либо проблемы, пожалуйста, не забудьте комментировать.
Оригинал: “https://dev.to/delta456/python-init-is-not-a-constructor-12on”