我可以在描述符的__init__方法中获得对'owner'类的引用吗?

时间:2011-05-21 18:41:39

标签: python python-2.5

是否可以在该描述符的__init__函数期间访问描述符内的“owner”类,而不是像本例中那样手动传递它?

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 个答案:

答案 0 :(得分: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装饰器返回一个只在ctor中只接受一个参数的类。

答案 1 :(得分:1)

从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