Рубрики
Без рубрики

Python: __init __ () не единственный конструктор

Многие новичков и даже программистов Pythonic считают, что __init __ () – конструктор, поскольку он инициализируется … Теги с Python, начинающими, учебниками.

Многие новичков и даже программистов 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”