Объект не принимает параметров после определения __new__ - PullRequest
0 голосов
/ 04 февраля 2019

В python 3.3 и более поздних версиях, когда мы переопределяем __new__(), нам не нужно передавать аргументы и аргументы ключевых слов в super().__new__() или object.__new__().Но этот вызов super().__new__() возвращает экземпляр класса.

Как python передает остальные аргументы __init__ тогда?

class Spam(object):
    ''' Hello I am Spam '''

    def __new__(cls, *args, **kwargs):
        print("Creating Instance")
        instance = object.__new__(cls) # Who passed *args and **kwargs to __init__?
        print(instance)
        return instance

    def __init__(self, a, b):
        print("Init Called")
        self.a = a
        self.b = b

Может кто-нибудь объяснить, что здесь происходит?

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Здесь важен начальный вызов, скажем spam = Spam('x', 1).

Внутренне Python вызывает __new__ как метод класса для класса Spam с переданными параметрами .То, что на самом деле делает Spam.__new__, на самом деле не важно, просто предполагается, что он возвращает объект.

Он использует object.__new__ для создания Spam объекта.Поскольку созданный объект имеет правильный класс, Python вызывает __init__ для него с начальными параметрами .

0 голосов
/ 04 февраля 2019

Вы передали cls в качестве аргумента object.__new__, поэтому интерпретатор может проверить, является ли instance экземпляром cls .

инициализатор ( __ init __ ) автоматически вызывается allocator ( __ new __ ) как [Python 3]: объект. __ new __ ( cls [, ...] ) ( выделено мои) состояния:

Если __ new __ () возвращает экземпляр cls , , тогда метод нового экземпляра __ init __ () будет вызываться как __init__(self[, ...]), где self - это новый экземпляр, а остальные аргументы такие же, как были переданы __ new __ () .

Если __ new __ () не возвращает экземпляр cls, тогда метод __ init __ () нового экземпляра будет не .

code.py:

#!/usr/bin/env python3

import sys


class Spam(object):
    ''' Hello I am Spam '''

    def __new__(cls, *args, **kwargs):
        print("Creating Instance")
        instance = object.__new__(cls) # Who passed *args and **kwargs to __init__?
        print(instance)
        #return instance  # If you return anything else (1, object(), or None by commenting the line) here, __init__ won't be called
        if len(sys.argv) == 1:  # DO NOT DO THIS!!! It's just for demo purposes
            return instance


    def __init__(self, a, b):
        print("Init Called")
        self.a = a
        self.b = b


def main():
    spam = Spam(1, 2)
    print(type(spam), dir(spam))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Выход :

e:\Work\Dev\StackOverflow\q054511671>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32

Creating Instance
<__main__.Spam object at 0x000001F8E24D14E0>
Init Called
<class '__main__.Spam'> ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b']

e:\Work\Dev\StackOverflow\q054511671>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py arg
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32

Creating Instance
<__main__.Spam object at 0x0000020808F71550>
<class 'NoneType'> ['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

Примечаниечто это не относится только к Python 3 (отметьте [Python 2]: модель данных ), а скорее к [Python]: New-Классы стиля Для получения более подробной информации вы также можете проверить check [Python 2.2]: Переопределение метода __new__ (класс Singleton ).

...