Django - цель использования super () и object.all ()? [Дубликат]

Как бы то ни было, ошибка также возникает, когда файл cpp, включенный в проект, не существует.

Если вы перечислите исходные файлы в CMakeLists.txt и ошибочно введите имя файла, тогда вы получите эту ошибку.

438
задан dreftymac 5 April 2017 в 21:08
поделиться

6 ответов

Преимущества super() в одиночном наследовании минимальны - в основном вам не нужно жестко закодировать имя базового класса во все методы, которые используют его родительские методы.

Однако использовать множественное наследование практически невозможно super(). Это включает в себя общие идиомы, такие как mixins, интерфейсы, абстрактные классы и т. Д. Это распространяется на код, который позже расширяет ваши. Если кто-то позже захотел написать класс, который расширил Child и mixin, их код не будет работать должным образом.

246
ответ дан John Millikin 16 August 2018 в 11:47
поделиться
214
ответ дан Aaron Hall 16 August 2018 в 11:47
поделиться

Я немного поиграл с super() и узнал, что мы можем изменить порядок вызова.

Например, у нас есть следующая структура иерархии:

    A
   / \
  B   C
   \ /
    D

In этот случай MRO of D будет (только для Python 3):

In [26]: D.__mro__
Out[26]: (__main__.D, __main__.B, __main__.C, __main__.A, object)

Давайте создадим класс, где super() вызывает после выполнения метода.

In [23]: class A(object): #  or with Python 3 can define class A:
...:     def __init__(self):
...:         print("I'm from A")
...:  
...: class B(A):
...:      def __init__(self):
...:          print("I'm from B")
...:          super().__init__()
...:   
...: class C(A):
...:      def __init__(self):
...:          print("I'm from C")
...:          super().__init__()
...:  
...: class D(B, C):
...:      def __init__(self):
...:          print("I'm from D")
...:          super().__init__()
...: d = D()
...:
I'm from D
I'm from B
I'm from C
I'm from A

    A
   / ⇖
  B ⇒ C
   ⇖ /
    D

Таким образом, мы можем видеть, что порядок разрешения такой же, как в MRO. Но когда мы назовем super() в начале метода:

In [21]: class A(object):  # or class A:
...:     def __init__(self):
...:         print("I'm from A")
...:  
...: class B(A):
...:      def __init__(self):
...:          super().__init__()  # or super(B, self).__init_()
...:          print("I'm from B")
...:   
...: class C(A):
...:      def __init__(self):
...:          super().__init__()
...:          print("I'm from C")
...:  
...: class D(B, C):
...:      def __init__(self):
...:          super().__init__()
...:          print("I'm from D")
...: d = D()
...: 
I'm from A
I'm from C
I'm from B
I'm from D

У нас есть другой порядок, он меняет порядок кортежа MRO.

    A
   / ⇘
  B ⇐ C
   ⇘ /
    D 

Для Дополнительное чтение Я бы рекомендовал следующие ответы:

  1. Пример линеаризации C3 с супер (большая иерархия)
  2. Важные изменения поведения между старыми и новые классы стиля
  3. Внутренняя история о классах нового стиля
20
ответ дан Community 16 August 2018 в 11:47
поделиться

class Child(SomeBaseClass): def __init__(self): SomeBaseClass.__init__(self) Это довольно легко понять.

class Child(SomeBaseClass): def __init__(self): super(Child, self).__init__()

Хорошо, что происходит сейчас, если вы используете super(Child,self)?

Когда создается экземпляр Child, его MRO (порядок разрешения метода) находится в порядке (Child, SomeBaseClass, object) на основе наследования. (предположим, что у SomeBaseClass нет других родителей, кроме объекта по умолчанию).

Передавая Child, self, super выполняет поиск в MRO экземпляра self и возвращает прокси-объект next of Child , в этом случае это SomeBaseClass, этот объект затем вызывает метод __init__ для SomeBaseClass. Другими словами, если это super(SomeBaseClass,self), то прокси-объект, который возвращает super, будет object

. Для множественного наследования MRO может содержать много классов, поэтому в основном super позволяет вам решить, где вы хотите начать поиск в MRO.

0
ответ дан dorisxx 16 August 2018 в 11:47
поделиться

Не все ли это предполагают, что базовый класс является классом нового стиля?

class A:
    def __init__(self):
        print("A.__init__()")

class B(A):
    def __init__(self):
        print("B.__init__()")
        super(B, self).__init__()

Не будет работать в Python 2. class A должен быть в стиле new, т. е. class A(object)

34
ответ дан Guillaume Jacquenot 16 August 2018 в 11:47
поделиться

При вызове super() для решения родительской версии метода класса, метода экземпляра или метода static мы хотим передать текущий класс, объем которого мы находимся в качестве первого аргумента, чтобы указать область действия родителя, которую мы пытаемся чтобы разрешить и в качестве второго аргумента объект интереса указать, к какому объекту мы пытаемся применить эту область.

Рассмотрим иерархию классов A, B и C где каждый класс является родителем следующего за ним и a, b и c соответствующих экземпляров каждого.

super(B, b) 
# resolves to the scope of B's parent i.e. A 
# and applies that scope to b, as if b was an instance of A

super(C, c) 
# resolves to the scope of C's parent i.e. B
# and applies that scope to c

super(B, c) 
# resolves to the scope of B's parent i.e. A 
# and applies that scope to c

Используя super со статическим методом

, например используя super() из метода __new__()

class A(object):
    def __new__(cls, *a, **kw):
        # ...
        # whatever you want to specialize or override here
        # ...

        return super(A, cls).__new__(cls, *a, **kw)

Объяснение:

1-, хотя обычно __new__() обычно принимает в качестве первого параметра ссылку на вызывающий класс, это not , реализованный в Python как classmethod, а скорее статический метод. То есть ссылка на класс должна быть явно передана в качестве первого аргумента при непосредственном вызове __new__():

# if you defined this
class A(object):
    def __new__(cls):
        pass

# calling this would raise a TypeError due to the missing argument
A.__new__()

# whereas this would be fine
A.__new__(A)

2- при вызове super() для перехода к родительскому классу мы передаем child class A в качестве своего первого аргумента, тогда мы передаем ссылку на объект, представляющий интерес, в этом случае это ссылка на класс, которая была передана при вызове A.__new__(cls). В большинстве случаев это также ссылка на дочерний класс. В некоторых ситуациях это может быть не так, например, в случае наследования с несколькими поколениями.

super(A, cls)

3-, поскольку поскольку общее правило __new__() является статическим методом, super(A, cls).__new__ также возвращает статический метод и должен быть предоставлен все аргументы явно, включая ссылку на объект insterest, в этом случае cls.

super(A, cls).__new__(cls, *a, **kw)

4- делать то же самое без super

class A(object):
    def __new__(cls, *a, **kw):
        # ...
        # whatever you want to specialize or override here
        # ...

        return object.__new__(cls, *a, **kw)

Использование super с помощью метода экземпляра

, например используя super() из __init__()

class A(object): 
    def __init__(self, *a, **kw):
        # ...
        # you make some changes here
        # ...

        super(A, self).__init__(*a, **kw)

Объяснение:

1- __init__ - это метод экземпляра, означающий, что в качестве первого аргумента он принимает ссылку на пример. При вызове непосредственно из экземпляра ссылка передается неявно, то есть вам не нужно указывать ее:

# you try calling `__init__()` from the class without specifying an instance
# and a TypeError is raised due to the expected but missing reference
A.__init__() # TypeError ...

# you create an instance
a = A()

# you call `__init__()` from that instance and it works
a.__init__()

# you can also call `__init__()` with the class and explicitly pass the instance 
A.__init__(a)

2- при вызове super() в __init__() мы передаем дочерний класс как первый аргумент и объект интереса как второй аргумент, который в общем случае является ссылкой на экземпляр дочернего класса.

super(A, self)

3- Вызов super(A, self) возвращает прокси-сервер, который будет разрешите область действия и примените ее к self, как если бы она стала экземпляром родительского класса. Назовем этот прокси s. Поскольку метод __init__() является методом экземпляра, вызов s.__init__(...) будет неявно передавать ссылку self в качестве первого аргумента родительскому __init__().

4- сделать то же самое без super нам нужно передать ссылку на экземпляр явно в родительскую версию __init__().

class A(object): 
    def __init__(self, *a, **kw):
        # ...
        # you make some changes here
        # ...

        object.__init__(self, *a, **kw)

Использование super с помощью метода класса

class A(object):
    @classmethod
    def alternate_constructor(cls, *a, **kw):
        print "A.alternate_constructor called"
        return cls(*a, **kw)

class B(A):
    @classmethod
    def alternate_constructor(cls, *a, **kw):
        # ...
        # whatever you want to specialize or override here
        # ...

        print "B.alternate_constructor called"
        return super(B, cls).alternate_constructor(*a, **kw)

Объяснение:

1- Метод класса можно вызывать непосредственно из класса и в качестве его первого параметра берет ссылку на класс.

# calling directly from the class is fine,
# a reference to the class is passed implicitly
a = A.alternate_constructor()
b = B.alternate_constructor()

2- при вызове super() в классе-методе, чтобы разрешить его родительскую версию, мы хотим передать текущий дочерний класс в качестве первого аргумента, чтобы указать, какую область действия родителя мы пытаемся разрешить и объект интереса в качестве второго аргумента, чтобы указать, к какому объекту мы хотим применить эту область действия, которая в общем случае является ссылкой на сам дочерний класс или один из его подклассов.

super(B, cls_or_subcls)

3- Вызов super(B, cls) разрешает область действия A и применяет ее к cls. Поскольку alternate_constructor() является методом класса, вызов super(B, cls).alternate_constructor(...) будет неявно передавать ссылку cls в качестве первого аргумента A alternate_constructor()

super(B, cls).alternate_constructor()

[4] для выполнения то же самое без использования super() вам нужно будет получить ссылку на unbound версию A.alternate_constructor() (то есть на явную версию функции). Просто это не сработает:

class B(A):
    @classmethod
    def alternate_constructor(cls, *a, **kw):
        # ...
        # whatever you want to specialize or override here
        # ...

        print "B.alternate_constructor called"
        return A.alternate_constructor(cls, *a, **kw)

Вышеупомянутое не будет работать, потому что метод A.alternate_constructor() принимает в качестве первого аргумента неявную ссылку на A. Здесь cls будет вторым аргументом.

class B(A):
    @classmethod
    def alternate_constructor(cls, *a, **kw):
        # ...
        # whatever you want to specialize or override here
        # ...

        print "B.alternate_constructor called"
        # first we get a reference to the unbound 
        # `A.alternate_constructor` function 
        unbound_func = A.alternate_constructor.im_func
        # now we call it and pass our own `cls` as its first argument
        return unbound_func(cls, *a, **kw)
15
ответ дан mike_e 16 August 2018 в 11:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: