Python 通过子类化'type'类实现类描述符
我想要一些数据描述符作为类的一部分。这意味着我希望类属性实际上是属性,其访问由类方法处理 Python似乎不直接支持这一点,但它可以通过子类化Python 通过子类化'type'类实现类描述符,python,class,properties,class-attributes,descriptor,Python,Class,Properties,Class Attributes,Descriptor,我想要一些数据描述符作为类的一部分。这意味着我希望类属性实际上是属性,其访问由类方法处理 Python似乎不直接支持这一点,但它可以通过子类化type类来实现。因此,将属性添加到类型的子类将导致其实例具有该属性的描述符。它的实例是类。因此,类描述符 这样做明智吗?有什么我应该注意的地方吗?这就是你所说的“类属性实际上是属性,其访问由类方法处理”的意思吗 您可以使用decorator属性使访问者看起来是实际的数据成员。然后,您可以使用x.setterdecorator为该属性创建一个setter
type
类来实现。因此,将属性添加到类型的子类
将导致其实例具有该属性的描述符。它的实例是类。因此,类描述符
这样做明智吗?有什么我应该注意的地方吗?这就是你所说的“类属性实际上是属性,其访问由类方法处理”的意思吗
您可以使用decorator属性
使访问者看起来是实际的数据成员。然后,您可以使用x.setter
decorator为该属性创建一个setter
请确保从对象继承,否则这将不起作用
class Foo(object):
def __init__(self):
self._hiddenx = 3
@property
def x(self):
return self._hiddenx + 10
@x.setter
def x(self, value):
self._hiddenx = value
p = Foo()
p.x #13
p.x = 4
p.x #14
当对类进行访问时,描述符通常会返回描述符对象本身。这就是属性
所做的;如果访问类上的属性对象,则会返回属性对象(因为这是\uuuu get\uuuu
方法选择执行的操作)。但这是一个惯例;你不必那样做
因此,如果您只需要在类上有一个getter描述符,并且您不介意尝试设置会覆盖描述符,那么您可以在不进行元类编程的情况下执行以下操作:
def classproperty_getter_only(f):
class NonDataDescriptor(object):
def __get__(self, instance, icls):
return f(icls)
return NonDataDescriptor()
class Foo(object):
@classproperty_getter_only
def flup(cls):
return 'hello from', cls
print Foo.flup
print Foo().flup
为了
('hello from',)
(“你好,我的朋友”,)
如果您想要一个完整的数据描述符,或者想要使用内置的属性对象,那么您是对的,您可以使用一个元类并将它放在那里(意识到这个属性在类的实例中是完全不可见的;在类的实例上执行属性查找时不会检查元类)
这样做明智吗?我不这么认为。我不会做您在生产代码中随意描述的事情;如果我有一个非常有说服力的理由去做的话,我只会考虑这个问题。元类功能非常强大,但并非所有程序员都能很好地理解它们,而且更难推理,因此元类的使用使代码更难维护。我认为这种设计会受到python社区的普遍反对。这个线程可能会有所帮助:事实上,它几乎是重复的,除了我明确询问了子类化类型
,而它只是在该问题的一个答案中建议的。不,我希望能够使用Foo.x
调用x(cls)
。非常好的响应,谢谢。当你说元类时,你是指我所描述的,即子类化类型
?这个术语似乎模棱两可,因为它不同于使用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。有没有办法区分这两个概念?或者子类化类型
是如此少以至于几乎没有必要吗?据我所知,子类化类型
只有当您将其用作元类时才真正有用。类与其元类之间的关系完全类似于对象实例与其类之间的关系。一个班级中的一个班级。当您打印MyClass时,会产生一个隐式的str(MyClass)
(我们打印的文本),实际被调用以生成该文本的方法是type.\uuu str\uuuu
(或者自定义元类上的\uu str\uuuu
方法)。元类定制通常在类构造期间进行,但也可以用其他方式进行定制。好了,我现在明白了。实际上,我调用元类时使用了一个3参数调用type
来创建类。我只是不明白\uuuuuuuuuuuuuuuuuu
做什么。我想我被文档中关于其影响发生在类构造中的断言弄糊涂了。但是类声明本身也是如此:)再次感谢。
('hello from', <class '__main__.Foo'>)
('hello from', <class '__main__.Foo'>)