[Python-3000] More PEP 3101 changes incoming
Talin
talin at acm.org
Thu Aug 16 09:09:39 CEST 2007
Carl Johnson wrote:
> (First, let me apologize for diving into a bike shed discussion.)
>
> There are two proposed ways to handle custom __format__ methods:
>
>> class MyInt:
>> def __format__(self, spec):
>> if int.is_int_specifier(spec):
>> return int(self).__format__(spec)
>> return "MyInt instance with custom specifier " + spec
>> def __int__(self):
>> return <some local state>
>
> and
>
>> class MyInt:
>> def __format__(self, spec):
>> if is_custom_spec(spec):
>> return "MyInt instance with custom specifier " + spec
>> return NotImplemented
>> def __int__(self):
>> return <some local state>
>
> I think this would be more straightforward as:
>
> class MyInt:
> def __format__(self, spec):
> if is_MyInt_specific_spec(spec):
> return "MyInt instance with custom specifier " + spec
> else:
> return int(self).__format__(spec)
> def __int__(self):
> return <some local state>
>
> The makers of the MyInt class should be the ones responsible for
> knowing that
> MyInt can be converted to int as needed for output. If they want
> MyInt to
> handle all the same format spec options as MyInt, it's up to them to
> either
> implement them all in their __format__ or to cast the instance object
> to int
> then call its __format__ object by themselves. I don't see the point
> in having
> format guess what MyInt should be converted to if it can't handle the
> options
> passed to it. If we go too far down this road, if MyInt craps out
> when given
> ":MM-DD-YY", then format will be obliged to try casting to Date just
> to see if
> it will work. No, I think the format function should be somewhat
> dumb, since
> dumb makes more sense to __format__ implementers than clever. Let
> them figure
> out what their type can be cast into.
+1
> In the case that regular int can't handle the given format spec either,
> int.__format__ will raise (return?) NotImplemented, in which case the
> format
> function will try string conversion, and then if that also pukes, a
> runtime
> exception should be raised.
>
> I also like the idea of using "!r" for calling repr and agree that it
> should be
> listed first. The syntax seems to be calling out for a little bit of
> extension
> though. Might it be nice to be able to do something like this?
>
> s = "10"
> print("{0!i:+d}".format(s)) #prints "+10"
It's been talked about extending it. The plan is to first implement the
more restricted version and let people hack on it, adding what features
are deemed useful in practice.
> The !i attempts to cast the string to int. If it fails, then an
> exception is
> raised. If it succeeds, then the int.__format__ method is used on the
> remainder
> of the spec string. The logic is that ! commands are abbreviated
> functions that
> are applied to the input before other formatting options are given.
>
> On the one hand, this does risk a descent into "line noise" if too
> many !
> options are provided. On the other hand, I think that providing !
> options for
> just repr, str, int, and float probably wouldn't be too bad, and
> might save
> some tedious writing of int(s), etc. in spots. It seems like if we're
> going to
> have a weird syntax for repr anyway, we might as well use it to make
> things
> more convenient in other ways. Or is this too TMTOWTDI-ish, since one
> could
> just write int(s) instead? (But by that logic, one could write repr
> (s) too…)
>
> The format function would end up looking like this:
>
> def format(obj, spec):
> if spec[0] == "!":
> switch statement for applying obj = repr(obj), obj = int
> (obj), etc.
> spec = spec[2:]
> if obj.__format__ and type(obj) is not str:
> try:
> #if spec contains letters not understood, __format__
> raises NI
> return obj.__format__(spec)
> except NotImplemented:
> pass #everything gets put through str as a last resort
> return str(obj).__format__(spec) #last chance before throwing
> exception
The built-in 'format' function doesn't handle '!r', that's done by the
caller. The 'spec' argument passed in to 'format' is the part *after*
the colon.
Also, there's no need to test for the existence __format__, because all
objects will have a __format__ method which is inherited from
object.__format__.
> Does this make sense to anyone else?
Perfectly.
> --Carl Johnson
> _______________________________________________
> Python-3000 mailing list
> Python-3000 at python.org
> http://mail.python.org/mailman/listinfo/python-3000
> Unsubscribe: http://mail.python.org/mailman/options/python-3000/talin%40acm.org
>
More information about the Python-3000
mailing list