[Python-ideas] Dunder method to make object str-like

Chris Angelico rosuav at gmail.com
Thu Apr 7 11:34:23 EDT 2016


On Fri, Apr 8, 2016 at 12:56 AM, Nathaniel Smith <njs at pobox.com> wrote:
> Why strings and not, say, floats or bools or lists or bytes? Is it because
> strings have a uniquely compelling use case, or...?
>
> (For context from the numpy side of things, since IIUC numpy's fixed-width
> integer types were the impetus for __index__: numpy actually has a shadow
> type system that has versions of all of those types above except list. It
> also has a general conversion/casting system with a concept of different
> levels of safety, so for us __index__ is like a "safe" cast to int, and
> __int__ is like a "unsafe", and we have versions of this for all pairs of
> internal types, which if you care about this in general then having a single
> parametrized concept of safe casting might make more sense then adding new
> methods one by one.
>
> I'm not aware of any particular pain points triggered by numpy's strings not
> being real strings, though, at least in numpy's current design.)

I'm not against there being more such "treat as" dunder methods, but
I'm not sure which types need them. We have __index__/__int__, and I'm
proposing adding __something__/__str__; bytes was mentioned in the
"okay folks, start bikeshedding" section.

With bool, I'm not sure there needs to be anything. What object would
need to say "I'm functionally a boolean!" in a way that's stronger
than truthiness/falsiness? In what context would it be appropriate to
use True and numpy.bool8(1) identically, but *not* use 42 or "spam" or
object() to also mean true? If there's a use-case for that, then sure,
that can be added to the proposal, and maybe something generic should
be added. +0.

Similar with float. I don't know of any use-cases myself, but I'd
guess numpy is the best place to look. Remember, though, this would
convert the other object into a float, not the float into a numpy
object; if you want that, stick with the existing dunder methods and
implement them yourself - numpy.float64(1.0)+2.0 is an instance of
numpy.float64, NOT float. +0.

With lists, though, I'm -1. The normal way to say "I function as a
list" is to implement sequence protocol. If you want to be able to
accept a list or a "thing like a list", what you usually want is a
Sequence.

So are you suggesting that we should instead have a single "safe cast"
dunder method?

class object:
    def __interpret_as__(self, t):
        """Return the same value as self, as an instance of t.

        If self cannot losslessly be interpreted as t, raise TypeError.
        """
        if self.__class__ is t: return self
        if t is int and hasattr(self, "__index__"):
            return self.__index__()
        raise TypeError("'%s' object cannot be interpreted as %s"
            % (self.__class__.__name__, t.__name__))

class Path:
    def __interpret_as__(self, t):
        if t is str: return str(self)
        return super().__interpret_as__(t)

Maybe that's the way things should be looking.

ChrisA


More information about the Python-ideas mailing list