[Python] How do you unwrap a python property to get attributes from the getter?

Discussão em 'Python' iniciado por Stack, Março 3, 2025.

  1. Stack

    Stack Membro Participativo

    From "outside", how can I access attributes in a property's getter function whether by unwrapping it or some other way?

    In a python property, its __get__ function seems to be a wrapper of a wrapper of a wrapper ...

    Using inspect.unwrap on the __get__ function returns another wrapper, not the getter. In fact, what unwrap returns seems to be the exact same object and id as what was unwrapped. See the MRE and its output below.

    Yes, I know that in simple cases I can get the attribute through classinstance.__class__.propertygetterfunction._privateattribute

    In my real situation, not the MRE below, the getter had been dynamically defined and is referenced only in synthesizing the property. Once created, there are no other references to the getter besides what is buried in the property.

    What is the path from aclass.aproperty.__get__ to the getter and its attributes?

    In the following MRE example, the getter contains one attribute containing how may times the getter has been called, and another containing the property's internal value.

    ref: https://medium.com/@genexu/extracti...a-decorator-on-python-call-stack-2ee2e48cdd8e

    from inspect import unwrap

    class propholder:
    def __init__(self):
    self.__class__.propgetter._usecount=0

    def propgetter(self):
    self.__class__.propgetter._usecount=self.__class__.propgetter._usecount +1
    print(f"getcount= {self.__class__.propgetter._usecount}")
    return self.__class__.propgetter._pvalue # set by the setter

    def propsetter(self, v):
    self.__class__.propgetter._pvalue=v

    # function to delete _age attribute
    def propdeleter(self):
    del self.__class__.propgetter
    del self.__class__.propsetter
    del self.__class__.propdeleter

    aprop = property(propgetter, propsetter, propdeleter)

    ap = propholder()

    for i in [10,11,12]:
    ap.aprop=i
    print(f" ap.aprop={ap.aprop} ")

    prop_get=ap.__class__.aprop.__get__
    u=unwrap(prop_get)
    print( f"\n prop_get=ap.__class__.aprop.__get__ = {prop_get} of type {prop_get.__class__} at {id(prop_get)} ")
    print( f" u=unwrap(prop_get) = {u} of type {u} at {id(u)} ")
    un=u
    for i in range(2,6):
    u=unwrap(u)
    print( f" u=unwrap(u) = {u} of type {u} at {id(u)} ")



    Results:


    getcount= 1
    ap.aprop=10
    getcount= 2
    ap.aprop=11
    getcount= 3
    ap.aprop=12

    prop_get=ap.__class__.aprop.__get__ = <method-wrapper '__get__' of property object at 0x72b6af94d940> of type <class 'method-wrapper'> at 126128955449232
    u=unwrap(prop_get) = <method-wrapper '__get__' of property object at 0x72b6af94d940> of type <method-wrapper '__get__' of property object at 0x72b6af94d940> at 126128955449232
    u=unwrap(u) = <method-wrapper '__get__' of property object at 0x72b6af94d940> of type <method-wrapper '__get__' of property object at 0x72b6af94d940> at 126128955449232
    u=unwrap(u) = <method-wrapper '__get__' of property object at 0x72b6af94d940> of type <method-wrapper '__get__' of property object at 0x72b6af94d940> at 126128955449232
    u=unwrap(u) = <method-wrapper '__get__' of property object at 0x72b6af94d940> of type <method-wrapper '__get__' of property object at 0x72b6af94d940> at 126128955449232
    u=unwrap(u) = <method-wrapper '__get__' of property object at 0x72b6af94d940> of type <method-wrapper '__get__' of property object at 0x72b6af94d940> at 126128955449232

    Continue reading...

Compartilhe esta Página