[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