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
