开发者

Can I get a reference to the 'owner' class during the __init__ method of a descriptor?

开发者 https://www.devze.com 2023-03-07 18:02 出处:网络
Is it possible to access the \'owner\' class inside a descriptor during the __init__ function of 开发者_如何转开发that descriptor, without passing it in manually as in this example?

Is it possible to access the 'owner' class inside a descriptor during the __init__ function of 开发者_如何转开发that descriptor, without passing it in manually as in this example?

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)


One way to do something like that is with a metaclass. Just make sure it's really what you want, and don't just copy blindly if you don't understand how it works.

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

If you need to pass additional arguments, you could use e.g. a tuple of (class, args) in the place of the class, or make FooDescriptor a decorator that would return a class that takes only one argument in the ctor.


Since Python 3.6, you can use the __set_name__ special method:

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__ is automatically called on all descriptors in a class immediately after the class is created. See PEP 487 for more details.

0

精彩评论

暂无评论...
验证码 换一张
取 消