[python] 파생 클래스에서이 속성을 덮어 쓰는 경우 기본 클래스의 속성을 호출하는 방법은 무엇입니까?

getter 및 setter의 광범위한 사용에서 속성의 비단뱀 사용으로 일부 클래스를 변경하고 있습니다.

하지만 이제는 이전 getter 또는 setter 중 일부가 기본 클래스의 해당 메서드를 호출 한 다음 다른 작업을 수행하기 때문에 문제가 발생합니다. 그러나 이것이 속성으로 어떻게 이루어질 수 있습니까? 부모 클래스에서 속성 getter 또는 setter를 호출하는 방법은 무엇입니까?

물론 속성 자체를 호출하는 것만으로도 무한 재귀를 얻을 수 있습니다.

class Foo(object):

    @property
    def bar(self):
        return 5

    @bar.setter
    def bar(self, a):
        print a

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return self.bar # --> recursion!

    @bar.setter
    def bar(self, c):
        # perform the same action
        # as in the base class
        self.bar = c    # --> recursion!
        # then do something else
        print 'something else'

fb = FooBar()
fb.bar = 7



답변

속성에 의해 호출되는 기본 클래스 함수를 호출 할 수 있다고 생각할 수 있습니다.

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar(self)

이것이 시도해 볼 수있는 가장 명백한 것임에도 불구하고 , bar는 콜 러블이 아니라 속성이기 때문에 작동하지 않습니다.

그러나 속성은 해당 속성을 찾는 getter 메서드가있는 개체 일뿐입니다.

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar.fget(self)


답변

Super 가 트릭을해야합니다.

return super().bar

Python 2.x에서는보다 자세한 구문을 사용해야합니다.

return super(FooBar, self).bar


답변

사용하는 대안이 있습니다 super기본 클래스 이름을 명시 적으로 참조 할 필요가없는 이 있습니다.

기본 등급 A :

class A(object):
    def __init__(self):
        self._prop = None

    @property
    def prop(self):
        return self._prop

    @prop.setter
    def prop(self, value):
        self._prop = value

class B(A):
    # we want to extend prop here
    pass

B에서 부모 클래스 A의 속성 getter에 액세스 :

다른 사람들이 이미 대답했듯이 다음과 같습니다.

super(B, self).prop

또는 Python 3에서 :

super().prop

이것은 getter 자체가 아니라 속성의 getter가 반환 한 값을 반환하지만 getter를 확장하는 것으로 충분합니다.

B에서 부모 클래스 A의 속성 setter에 액세스 :

지금까지 본 최고의 권장 사항은 다음과 같습니다.

A.prop.fset(self, value)

나는 이것이 더 낫다고 믿는다.

super(B, self.__class__).prop.fset(self, value)

이 예에서 두 옵션은 모두 동일하지만 super를 사용하면의 기본 클래스와 독립적이라는 이점이 B있습니다. 속성을 확장 B하는 C클래스 에서 상속하는 경우 B의 코드 를 업데이트 할 필요가 없습니다 .

A의 속성을 확장하는 B의 전체 코드 :

class B(A):
    @property
    def prop(self):
        value = super(B, self).prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        super(B, self.__class__).prop.fset(self, value)

한 가지주의 사항 :

속성에 setter가 없으면 둘 B중 하나의 동작 만 변경하더라도 setter와 getter를 모두 정의 해야합니다.


답변

시험

@property
def bar:
    return super(FooBar, self).bar

파이썬이 기본 클래스 속성 호출을 지원하는지 확실하지 않지만. 속성은 실제로 지정된 함수로 설정된 다음 클래스에서 해당 이름을 대체하는 호출 가능한 객체입니다. 이것은 사용 가능한 슈퍼 기능이 없음을 쉽게 의미 할 수 있습니다.

그래도 항상 property () 함수를 사용하도록 구문을 전환 할 수 있습니다.

class Foo(object):

    def _getbar(self):
        return 5

    def _setbar(self, a):
        print a

    bar = property(_getbar, _setbar)

class FooBar(Foo):

    def _getbar(self):
        # return the same value
        # as in the base class
        return super(FooBar, self)._getbar()

    def bar(self, c):
        super(FooBar, self)._setbar(c)
        print "Something else"

    bar = property(_getbar, _setbar)

fb = FooBar()
fb.bar = 7


답변

Maxime의 답변에 대한 몇 가지 작은 개선 사항 :

  • __class__쓰기를 피하기 위해 사용 B. 주 self.__class__의 실행시의 형태이다 self,하지만 __class__ 하지 않고는 self 바깥 쪽 클래스 정의의 이름입니다. super()super(__class__, self).
  • 사용 __set__대신에 fset. 후자는 propertys에만 해당되지만 전자는 모든 속성 유사 객체 (설명자)에 적용됩니다.
class B(A):
    @property
    def prop(self):
        value = super().prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        super(__class__, self.__class__).prop.__set__(self, value)


답변

다음 템플릿을 사용할 수 있습니다.

class Parent():
    def __init__(self, value):
        self.__prop1 = value

    #getter
    @property
    def prop1(self):
        return self.__prop1

    #setter
    @prop1.setter
    def prop1(self, value):
        self.__prop1 = value

    #deleter
    @prop1.deleter
    def prop1(self):
        del self.__prop1

class Child(Parent):

    #getter
    @property
    def prop1(self):
        return super(Child, Child).prop1.__get__(self)

    #setter
    @prop1.setter
    def prop1(self, value):
        super(Child, Child).prop1.__set__(self, value)

    #deleter
    @prop1.deleter
    def prop1(self):
        super(Child, Child).prop1.__delete__(self)

노트! 모든 속성 메서드를 함께 다시 정의해야합니다. 모든 방법을 재정의하지 않으려면 대신 다음 템플릿을 사용하십시오.

class Parent():
    def __init__(self, value):
        self.__prop1 = value

    #getter
    @property
    def prop1(self):
        return self.__prop1

    #setter
    @prop1.setter
    def prop1(self, value):
        self.__prop1 = value

    #deleter
    @prop1.deleter
    def prop1(self):
        del self.__prop1


class Child(Parent):

    #getter
    @Parent.prop1.getter
    def prop1(self):
        return super(Child, Child).prop1.__get__(self)

    #setter
    @Parent.prop1.setter
    def prop1(self, value):
        super(Child, Child).prop1.__set__(self, value)

    #deleter
    @Parent.prop1.deleter
    def prop1(self):
        super(Child, Child).prop1.__delete__(self)


답변

    class Base(object):
      def method(self):
        print "Base method was called"

    class Derived(Base):
      def method(self):
        super(Derived,self).method()
        print "Derived method was called"

    d = Derived()
    d.method()

(당신의 설명에서 빠진 것이 없다면)