Skip to content

Expand and clarify the "Invoking Descriptors" section of the Descriptor HowTo #23078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 1, 2020

Conversation

rhettinger
Copy link
Contributor

  • Various minor edits
  • Break "Invoking Descriptors" into subsections
  • Add pure python equivalent code for object.__getattribute__()

@rhettinger
Copy link
Contributor Author

rhettinger commented Nov 1, 2020

For the record, here's the test code for the pure python equivalent:

class A:

    x = 10

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

    @property
    def p2(self):
        return 2 * self.x

    @property
    def p3(self):
        return 3 * self.x

    def m5(self, y):
        return 5 * y

    def m7(self, y):
        return 7 * y

    def __getattr__(self, name):
        return ('getattr_hook', self, name)

    # def object_getattribute(obj, name):
    def __getitem__(obj, name):
        "Emulate PyObject_GenericGetAttr() in Objects/object.c"
        null = object()
        objtype = type(obj)
        value = getattr(objtype, name, null)
        if value is not null and hasattr(value, '__get__'):
            if hasattr(value, '__set__') or hasattr(value, '__delete__'):
                return value.__get__(obj, objtype)  # data descriptor
        try:
            return vars(obj)[name]                  # instance variable
        except (KeyError, TypeError):
            pass
        if hasattr(value, '__get__'):
            return value.__get__(obj, objtype)      # non-data descriptor
        if value is not null:
            return value                            # class variable
        # Emulate slot_tp_getattr_hook() in Objects/typeobject.c
        if hasattr(objtype, '__getattr__'):
            return objtype.__getattr__(obj, name)   # __getattr__ hook
        raise AttributeError(name)

class B:
    __slots__ = ['z']

    x = 15

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

    @property
    def p2(self):
        return 2 * self.x

    def m5(self, y):
        return 5 * y

    def __getattr__(self, name):
        return ('getattr_hook', self, name)

    __getitem__ = A.__getitem__

if __name__ == '__main__':

    a = A(11)
    vars(a).update(p3 = '_p3', m7 = '_m7')
    assert a.x == a['x'] == 10
    assert a.z == a['z'] == 11
    assert a.p2 == a['p2'] == 20
    assert a.p3 == a['p3'] == 30
    assert a.m5(100) == a.m5(100) == 500
    assert a.m7 == a['m7'] == '_m7'
    assert a.g == a['g'] == ('getattr_hook', a, 'g')

    b = B(22)
    assert b.x == b['x'] == 15
    assert b.z == b['z'] == 22
    assert b.p2 == b['p2'] == 30
    assert b.m5(200) == b['m5'](200) == 1000
    assert b.g == b['g'] == ('getattr_hook', b, 'g')

    print('Success.  All tests passed.')

@rhettinger rhettinger merged commit 148c76b into python:master Nov 1, 2020
@miss-islington
Copy link
Contributor

Thanks @rhettinger for the PR 🌮🎉.. I'm working now to backport this PR to: 3.9.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Nov 1, 2020
…or HowTo (pythonGH-23078)

(cherry picked from commit 148c76b)

Co-authored-by: Raymond Hettinger <[email protected]>
@bedevere-bot bedevere-bot removed the needs backport to 3.9 only security fixes label Nov 1, 2020
@bedevere-bot
Copy link

GH-23080 is a backport of this pull request to the 3.9 branch.

@rhettinger rhettinger deleted the descriptor_tutorial_4 branch November 1, 2020 17:10
adorilson pushed a commit to adorilson/cpython that referenced this pull request Mar 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir skip issue skip news
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants