在描述符的__init__方法中,我能获取'owner'类的引用吗?
在描述符的__init__
函数中,是否可以直接访问“拥有者”类,而不需要像这个例子那样手动传递它?
class FooDescriptor(object):
def __init__(self, owner):
#do things to owner here
setattr(owner, 'bar_attribute', 'bar_value')
class BarClass(object):
foo_attribute = FooDescriptor(owner=BarClass)
2 个回答
4
从Python 3.6开始,你可以使用一个叫做__set_name__
的特殊方法:
class FooDescriptor(object):
def __set_name__(self, owner, name):
owner.foo = 42
class BarClass(object):
foo_attribute = FooDescriptor()
# foo_attribute.__set_name__(BarClass, "foo_attribute") called after class definition
每当一个类被创建后,__set_name__
会自动在这个类里的所有描述符上被调用。想了解更多,可以查看PEP 487。
4
实现类似功能的一种方法是使用元类。确保这确实是你想要的,不要盲目复制,如果你不理解它是怎么工作的。
class Descriptor(object):
pass
class Meta(type):
def __new__(cls, name, bases, attrs):
obj = type.__new__(cls, name, bases, attrs)
# obj is now a type instance
# this loop looks for Descriptor subclasses
# and instantiates them, passing the type as the first argument
for name, attr in attrs.iteritems():
if isinstance(attr, type) and issubclass(attr, Descriptor):
setattr(obj, name, attr(obj))
return obj
class FooDescriptor(Descriptor):
def __init__(self, owner):
owner.foo = 42
class BarClass(object):
__metaclass__ = Meta
foo_attribute = FooDescriptor # will be instantiated by the metaclass
print BarClass.foo
如果你需要传递额外的参数,可以用一个元组,比如 (class, args)
来代替类,或者把 FooDescriptor
做成一个装饰器,这样它就可以返回一个只在构造函数中接受一个参数的类。