Home > Software engineering >  Mimic a descriptor with a function
Mimic a descriptor with a function

Time:02-10

I am trying to mimic a descriptor with a decorator function, but have failed. Here's what I have tried.

def my_property(self):
    def wrapper(func):        
        return func(self)
    return wrapper

class C:
    def __init__(self):
        self._x = 0

    @my_property(C()) # this will print 0 for me, but it's not from the obj `c`
    def p(self):
        return self._x    

c = C()
print(c.p)

Overriding __get__ directly in the decorator didn't help me either. I also tried to inherit the function class and override its __get__ method, but was told function is final and not subclassable (probably I should try forbiddenfruit https://github.com/clarete/forbiddenfruit).

Can anyone help?

Edit: To clarify, I was wondering if it is possible without having to use the keyword class?

CodePudding user response:

Your intuition is right to override __get__. In fact, that's exactly how properties in Python actually work.

Consider

class MyProperty:

    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        return self.func(instance)

MyProperty is a class whose instances contain a func. When we __get__ an instance of MyProperty off a class, it'll call the inner function automatically.

Now we'll make a neat wrapper function for it. Pretty trivial, but still nice to be consistent with Python's nomenclature for functions vs. types

def my_property(func):
    return MyProperty(func)

Finally, using the decorator.

class C:
    def __init__(self):
        self._x = 0

    @my_property
    def p(self):
        return self._x

c = C()
print(c.p) # Prints 0
  •  Tags:  
  • Related