Skip to content

Possible bug with super() in combination with descriptor #7

Description

@smarie

From the documentation

The attribute lookup super(B, obj).m searches obj.class.mro for the base class A immediately following B and then returns A.dict['m'].get(obj, B). If not a descriptor, m is returned unchanged. If not in the dictionary, m reverts to a search using object.getattribute().

It seems that at least in some cases this leads to counterintuitive behaviour, and falling back to A.__dict__['m'].__get__(obj, A) (note the change in owner from B to A) seems preferable. Is that a particular case for pyfields because we have a descriptor for the __init__ method and therefore would like it to "stay" on A once called, or would this be preferable in all cases ?

class AInitDescriptor(object):
    def __get__(self, instance, owner):
        print("called on instance %s - creating init for owner class %s" % (instance, owner.__name__))
        def __init__():
            pass
        
        # Assign the __init__ method to the class
        if owner.__name__ != 'A':
            raise ValueError("This is the __init__ descriptor for A, not for %s!" % owner.__name__)
        owner.__init__ = __init__

        # finally return
        return __init__

class A(object):
    __init__ = AInitDescriptor()

class B(A):
    def __init__(self):
        super(B, self).__init__()


# this leads to an error
b = B()

Note that trivial workarounds for this specific example can be found, but the general question remains interesting to discuss.

See smarie/python-pyfields#53 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions