Уникальное поле для уникального id [duplicate]

При вызове 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)
10
задан Nick Parsons 11 January 2013 в 20:06
поделиться

1 ответ

Вы можете применить это, используя уникальный индекс, который включает оба поля:

submissionSchema.index({ email: 1, sweepstakes_id: 1 }, { unique: true });
44
ответ дан JohnnyHK 21 August 2018 в 01:31
поделиться
Другие вопросы по тегам:

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