클래스 메소드 장식 함수와 함께 property () 함수를 사용할 수 있습니까?
아니.
그러나 클래스 메소드는 단순히 해당 클래스의 인스턴스에서 액세스 할 수있는 클래스의 바인딩 된 메소드 (일부 함수)입니다.
인스턴스는 클래스의 함수이므로 인스턴스에서 클래스를 파생시킬 수 있으므로 다음을 사용하여 클래스 속성에서 원하는 동작을 얻을 수 있습니다 property
.
class Example(object):
_class_property = None
@property
def class_property(self):
return self._class_property
@class_property.setter
def class_property(self, value):
type(self)._class_property = value
@class_property.deleter
def class_property(self):
del type(self)._class_property
이 코드는 테스트하는 데 사용될 수 있습니다. 오류없이 발생해야합니다.
ex1 = Example()
ex2 = Example()
ex1.class_property = None
ex2.class_property = 'Example'
assert ex1.class_property is ex2.class_property
del ex2.class_property
assert not hasattr(ex1, 'class_property')
그리고 우리는 메타 클래스가 전혀 필요하지 않았으며 클래스의 인스턴스를 통해 메타 클래스에 직접 액세스하지 않습니다.
@classproperty
데코레이터 작성
classproperty
서브 클래 싱을 통해 몇 줄의 코드로 데코레이터를 실제로 만들 수 있습니다 property
(C로 구현되었지만 여기에서 동등한 Python을 볼 수 있습니다 ).
class classproperty(property):
def __get__(self, obj, objtype=None):
return super(classproperty, self).__get__(objtype)
def __set__(self, obj, value):
super(classproperty, self).__set__(type(obj), value)
def __delete__(self, obj):
super(classproperty, self).__delete__(type(obj))
그런 다음 데코레이터를 속성과 결합 된 클래스 메소드처럼 취급하십시오.
class Foo(object):
_bar = 5
@classproperty
def bar(cls):
"""this is the bar attribute - each subclass of Foo gets its own.
Lookups should follow the method resolution order.
"""
return cls._bar
@bar.setter
def bar(cls, value):
cls._bar = value
@bar.deleter
def bar(cls):
del cls._bar
그리고이 코드는 오류없이 작동해야합니다.
def main():
f = Foo()
print(f.bar)
f.bar = 4
print(f.bar)
del f.bar
try:
f.bar
except AttributeError:
pass
else:
raise RuntimeError('f.bar must have worked - inconceivable!')
help(f) # includes the Foo.bar help.
f.bar = 5
class Bar(Foo):
"a subclass of Foo, nothing more"
help(Bar) # includes the Foo.bar help!
b = Bar()
b.bar = 'baz'
print(b.bar) # prints baz
del b.bar
print(b.bar) # prints 5 - looked up from Foo!
if __name__ == '__main__':
main()
그러나 이것이 얼마나 잘 충고되었는지는 확실하지 않습니다. 오래된 메일 링리스트 기사에 따르면 작동하지 않아야합니다.
강의실에서 숙소를 이용하기 :
위의 단점은 "클래스 속성"은 클래스에서 데이터 디스크립터를 덮어 쓰기 때문에 클래스에서 액세스 할 수 없다는 것 __dict__
입니다.
그러나 metaclass에 정의 된 속성으로이를 재정의 할 수 있습니다 __dict__
. 예를 들면 다음과 같습니다.
class MetaWithFooClassProperty(type):
@property
def foo(cls):
"""The foo property is a function of the class -
in this case, the trivial case of the identity function.
"""
return cls
그런 다음 메타 클래스의 클래스 인스턴스는 이전 섹션에서 이미 설명한 원칙을 사용하여 클래스의 속성에 액세스하는 속성을 가질 수 있습니다.
class FooClassProperty(metaclass=MetaWithFooClassProperty):
@property
def foo(self):
"""access the class's property"""
return type(self).foo
이제 우리는 두 인스턴스를 모두 본다
>>> FooClassProperty().foo
<class '__main__.FooClassProperty'>
그리고 수업
>>> FooClassProperty.foo
<class '__main__.FooClassProperty'>
클래스 속성에 액세스 할 수 있습니다.