Closed laundmo closed 3 years ago
Well, it's quite some time ago that I really thought about this and decided that this is the best way to go. If I remember correctly, I deduced that this behaviour is less surprising.
Ah, I've documented it in the code. :-)
@property
def self(self):
"""Returns the previous wrapped object. This is especially usefull for APIs that return None.
For example ``_([1,3,2]).sort().self.print()`` will print the sorted list, even though
``sort()`` did return ``None``.
This is simpler than using .previous as there are often multiple wrappers involved where you might expect only one.
E.g. ``_([2,1]).sort().self._ == [1,2]`` but ``_([2,1]).sort().previous._`` will return the function ``list.sort()``
as the attrget and call are two steps of the call chain.
This eases chaining using APIs that where not designed with chaining in mind.
(Inspired by SmallTalk's default behaviour)
"""
# This behavior is always triggered, not just in the `None` return case to avoid
# code that behaves differently for methods that _sometimes_ return `None`.
# Depending on wether the previous method was a transplanted method
# we need to go back one level or two
if isinstance(self.previous, CallableWrapper):
return self.previous.previous
else:
return self.previous
I think that is still quite a valid reason - code that sometimes returns None and sometimes doesn't would trigger really strange bugs otherwise. Or am I missing something?
You are right, i had not considered methods that sometimes return none. It might be possible to use AST to look up whether there is any explicit returns in the function, and only fall back if the only possible return is the implicit None, but that seems like a lot of effort.
Yes. And probably brittle as hell, given that things like decorators will wreak havoc with this. I'll close this for now, if there's anything we missed, feel freer to reopen / add to the conversation.
What is the reasoning for not falling back to self automatically if a wrapped function returns None?
for example,
would be way nicer than
Could there be a option to enable such a fallback?