Özellik () işlevini, sınıf yöntemiyle dekore edilmiş işlevlerle kullanmak mümkün müdür?
Hayır.
Ancak, bir sınıf yöntemi, o sınıfın örneklerinden erişilebilen bir sınıfa bağlı bir yöntemdir (kısmi bir işlev).
Örnek sınıfın bir işlevi olduğundan ve sınıfı örnekten türetebildiğinizden, bir sınıf özelliğinden istediğiniz her türlü davranışı aşağıdakilerle elde edebilirsiniz 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
Bu kod test etmek için kullanılabilir - herhangi bir hata oluşturmadan geçmelidir:
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')
Ve hiçbir zaman metasınıflara ihtiyacımız olmadığını unutmayın - ve yine de sınıflarının örnekleri aracılığıyla bir metastata doğrudan erişemezsiniz.
@classproperty
dekoratör yazmak
Aslında classproperty
alt sınıflama ile sadece birkaç kod satırında bir dekoratör oluşturabilirsiniz property
(C'de uygulanır, ancak burada eşdeğer Python'u görebilirsiniz ):
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))
Sonra dekoratöre, özellikle birleştirilmiş bir sınıf yöntemi gibi davranın:
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
Ve bu kod hatasız çalışmalıdır:
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()
Ama bunun ne kadar iyi tavsiye edileceğinden emin değilim. Eski bir posta listesi makalesi , çalışmaması gerektiğini gösteriyor.
Özelliğin sınıf üzerinde çalışmasını sağlama:
Yukarıdakilerin dezavantajı, "sınıf özelliğine" sınıftan erişilememesidir, çünkü sınıftan veri tanımlayıcısının üzerine yazacaktır __dict__
.
Ancak, bunu metasınıfta tanımlanan bir özellik ile geçersiz kılabiliriz __dict__
. Örneğin:
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
Ve sonra metasınıfın bir sınıf örneği, önceki bölümlerde zaten gösterilen prensibi kullanarak sınıfın özelliğine erişen bir özelliğe sahip olabilir:
class FooClassProperty(metaclass=MetaWithFooClassProperty):
@property
def foo(self):
"""access the class's property"""
return type(self).foo
Ve şimdi ikisini de görüyoruz
>>> FooClassProperty().foo
<class '__main__.FooClassProperty'>
ve sınıf
>>> FooClassProperty.foo
<class '__main__.FooClassProperty'>
class özelliğine erişebilir.