파이썬 특성 및 상속
-
04-07-2019 - |
문제
서브 클래스로 덮어 쓰고 싶은 속성이있는 기본 클래스가 있습니다. 내 첫 생각은 다음과 같습니다.
class Foo(object):
def _get_age(self):
return 11
age = property(_get_age)
class Bar(Foo):
def _get_age(self):
return 44
이것은 작동하지 않습니다 (서브 클래스 바 .age 11). 나는 Lambda 표현이있는 솔루션을 찾았습니다.
age = property(lambda self: self._get_age())
그렇다면 이것은 속성을 사용하는 올바른 솔루션이며 서브 클래스로 덮어 쓰거나 다른 선호하는 방법이 있습니까?
해결책
나는 단순히 반복하는 것을 선호합니다 property()
뿐만 아니라 당신은 반복 할 것입니다 @classmethod
클래스 방법을 재정의 할 때 데코레이터.
이것은 적어도 Python 표준의 경우 매우 장황한 것처럼 보이지만 다음과 같은 것을 알 수 있습니다.
1) 읽기 전용 속성의 경우 property
데코레이터로 사용할 수 있습니다.
class Foo(object):
@property
def age(self):
return 11
class Bar(Foo):
@property
def age(self):
return 44
2) Python 2.6에서 속성은 한 쌍의 방법으로 성장했습니다 setter
그리고 deleter
일반 속성에 적용하는 데 사용할 수 있습니다. 이미 읽기 전용으로 사용 가능한 바로 가기입니다.
class C(object):
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
다른 팁
선택한 답변이 속성 방법을 무시할 수있는 이상적인 방법이라는 데 동의하지 않습니다. Getters와 Setter가 무시 될 것으로 예상되면 Lambda를 사용하여 자신에게 접근 할 수 있습니다. lambda self: self.<property func>
.
이것은 Python 버전 2.4 ~ 3.6의 경우 (적어도) 작동합니다.
직접 속성 () 호출 대신 데코레이터로 속성을 사용 하여이 작업을 수행하는 방법을 알고 있다면 듣고 싶습니다.
예시:
class Foo(object):
def _get_meow(self):
return self._meow + ' from a Foo'
def _set_meow(self, value):
self._meow = value
meow = property(fget=lambda self: self._get_meow(),
fset=lambda self, value: self._set_meow(value))
이런 식으로 재정의를 쉽게 수행 할 수 있습니다.
class Bar(Foo):
def _get_meow(self):
return super(Bar, self)._get_meow() + ', altered by a Bar'
하도록 하다:
>>> foo = Foo()
>>> bar = Bar()
>>> foo.meow, bar.meow = "meow", "meow"
>>> foo.meow
"meow from a Foo"
>>> bar.meow
"meow from a Foo, altered by a Bar"
나는 이것을 발견했다 놀이 치는 괴짜.
추가 수업을 만들 필요없이이를 수행하는 또 다른 방법. 두 가지 중 하나만 재정의 경우 귀하가 수행하는 작업을 보여주는 세트 메소드를 추가했습니다.
class Foo(object):
def _get_age(self):
return 11
def _set_age(self, age):
self._age = age
age = property(_get_age, _set_age)
class Bar(Foo):
def _get_age(self):
return 44
age = property(_get_age, Foo._set_age)
이것은 꽤 고안된 예이지만 아이디어를 얻어야합니다.
예, 이것이하는 방법입니다. 부동산 선언은 상위 클래스의 정의가 실행될 때 실행됩니다. 즉, 부모 클래스에 존재하는 메소드의 버전 만 "볼 수 있습니다. 따라서 자식 수업에서 해당 메소드 중 하나 이상을 재정의 할 때는 메소드의 어린이 클래스 버전을 사용하여 속성을 다시 해제해야합니다.
나는 당신의 솔루션에 동의하며, 이는 비행기 템플릿 방법으로 보입니다.이 기사 문제를 처리하고 솔루션을 정확하게 제공합니다.
이와 같은 것이 효과가 있습니다
class HackedProperty(object):
def __init__(self, f):
self.f = f
def __get__(self, inst, owner):
return getattr(inst, self.f.__name__)()
class Foo(object):
def _get_age(self):
return 11
age = HackedProperty(_get_age)
class Bar(Foo):
def _get_age(self):
return 44
print Bar().age
print Foo().age
동일 @MR-B그러나 데코레이터와 함께.
class Foo(object):
def _get_meow(self):
return self._meow + ' from a Foo'
def _set_meow(self, value):
self._meow = value
@property
def meow(self):
return self._get_meow()
@meow.setter
def meow(self, value):
self._set_meow(value)
이런 식으로 재정의를 쉽게 수행 할 수 있습니다.
class Bar(Foo):
def _get_meow(self):
return super(Bar, self)._get_meow() + ', altered by a Bar'
나는 아동 수업에서 부모 수업에서 재산을 설정하는 데 문제가있었습니다. 다음 워크 라운드는 부모의 속성을 확장하지만 부모의 _set_age 메소드를 직접 호출하여 그렇게합니다. 주름진은 항상 정확해야합니다. 그래도 조금 javathonic입니다.
import threading
class Foo(object):
def __init__(self):
self._age = 0
def _get_age(self):
return self._age
def _set_age(self, age):
self._age = age
age = property(_get_age, _set_age)
class ThreadsafeFoo(Foo):
def __init__(self):
super(ThreadsafeFoo, self).__init__()
self.__lock = threading.Lock()
self.wrinkled = False
def _get_age(self):
with self.__lock:
return super(ThreadsafeFoo, self).age
def _set_age(self, value):
with self.__lock:
self.wrinkled = True if value > 40 else False
super(ThreadsafeFoo, self)._set_age(value)
age = property(_get_age, _set_age)