Skip to main content
added 1 character in body
Source Link
Olivier Melançon
  • 22.5k
  • 4
  • 48
  • 81

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def _resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return _resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = _resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits a few steps for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtin  getattr would.

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def _resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return _resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = _resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits a few steps for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtingetattr would.

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def _resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return _resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = _resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits a few steps for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtin  getattr would.

added 1 character in body
Source Link
Olivier Melançon
  • 22.5k
  • 4
  • 48
  • 81

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def _resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return _resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = _resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits afew casesa few steps for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtingetattr would.

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def _resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return _resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = _resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits afew cases for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtingetattr would.

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def _resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return _resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = _resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits a few steps for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtingetattr would.

added 3 characters in body
Source Link
Olivier Melançon
  • 22.5k
  • 4
  • 48
  • 81

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def resolve_cls_attr_resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return resolve_cls_attr_resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = resolve_cls_attr_resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits afew cases for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtingetattr would.

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits afew cases for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtingetattr would.

You are partially correct, let's start by what you got wrong.

Should I think of inheritance as simply creating pointers to the base class objects

That would be incorrect. When you access an attribute, either with getattr(obj, attr) or by doing obj.attr, Python first recovers the attribute through the method resolution order. In particular this means that this does not happen at class creation, but at attribute lookup instead.

It looks as if Python creates an attribute foo which is bound to A.foo

Here you are correct. Binding a class or instance method created a new object in the process.

After having recovered the attribute, Python may need to bind it. It first checks if it is a descriptor, that is an object with a __get__ method to allow binding it to a certain instance.

Here is a Python implementation of the getattr to help visualize what happens when you retrieve an attribute.

First this is how Python resolves a class attribute using the mro.

def _resolve_cls_attr(cls, attr):
    if attr in cls.__dict__:
        return cls.__dict__[attr]

    elif len(cls.__mro__) > 1:
        return _resolve_cls_attr(cls.__mro__[1], attr)

    else:
        raise AttributeError('class has no attribute {}'.format(attr))

Then, this is how getattr would be implemented if it were in Python.

def getattr(instance, attr):
    cls = instance if isinstance(instance, type) else type(instance)

    # Recover instance attribute
    if hasattr(instance, '__dict__') and attr in instance.__dict__:
        attr_value = instance.__dict__[attr]

    # Recover the attribute from the class
    else:
        attr_value = _resolve_cls_attr(cls, attr)

    # We recovered a simple class attribute
    if not hasattr(attr_value, '__get__'):
        return attr_value

    # We recovered an instance method from a class or a staticmethod descriptor
    if instance is cls or isinstance(attr_value, staticmethod):
        return attr_value.__get__(None, cls)

    # We recovered an instance method or a custom descriptor
    return attr_value.__get__(instance, cls)

Keep in mind that the above omits afew cases for the sake of sticking to your question. By example, it will not rely on __getattr__ and __getattribute__ as the builtingetattr would.

deleted 213 characters in body
Source Link
Olivier Melançon
  • 22.5k
  • 4
  • 48
  • 81
Loading
added 428 characters in body
Source Link
Olivier Melançon
  • 22.5k
  • 4
  • 48
  • 81
Loading
Source Link
Olivier Melançon
  • 22.5k
  • 4
  • 48
  • 81
Loading