Ivan Velichko Ivan Velichko - 11 days ago 7
Python Question

How does Python distinguish explicitly passed None as argument in built-ins

I experimented with the next code:

>>> f = object()

# It's obvious behavior:
>>> f.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'

# However, the next one is surprising me!
>>> getattr(f, 'foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'

# And this one returns None as expected:
>>> getattr(f, 'foo', None)


Then I found this pseudo-signature of
getattr()
in the PyCharm IDE:

def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value

Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass


My question is how does python distinguish this two scenarios of using
getattr()
(and maybe other functions) internally? And is it possible to do something similar entirely in the client side code?

Answer

As @scytale said, the pseudo-signature of getattr doesn't quite correspond to its implementations. I've seen attempts to replicate the behaviour in pure Python that look something like this:

class MyObject(object):
    __marker = object

    def getvalue(key, default=__marker):
        ...
        if key is __marker:
             # no value supplied for default
             ....

In other words, use a marker value that a caller cannot easily supply to check if no value was given as the default rather than None.