[Python-Dev] PEP 467: last round (?)

Ethan Furman ethan at stoneleaf.us
Mon Sep 5 12:58:42 EDT 2016


On 09/03/2016 09:48 AM, Nick Coghlan wrote:
> On 3 September 2016 at 21:35, Martin Panter wrote:
>> On 3 September 2016 at 08:47, Victor Stinner wrote:
>>> Le samedi 3 septembre 2016, Random832 a écrit :
>>>> On Fri, Sep 2, 2016, at 19:44, Ethan Furman wrote:

>>>>> The problem with only having `bchr` is that it doesn't help with
>>>>> `bytearray`;
>>>>
>>>> What is the use case for bytearray.fromord? Even in the rare case
>>>> someone needs it, why not bytearray(bchr(...))?
>>>
>>> Yes, this was my point: I don't think that we need a bytearray method to
>>> create a mutable string from a single byte.
>>
>> I agree with the above. Having an easy way to turn an int into a bytes
>> object is good. But I think the built-in bchr() function on its own is
>> enough. Just like we have bytes object literals, but the closest we
>> have for a bytearray literal is bytearray(b". . .").
>
> This is a good point - earlier versions of the PEP didn't include
> bchr(), they just had the class methods, so "bytearray(bchr(...))"
> wasn't an available spelling (if I remember the original API design
> correctly, it would have been something like
> "bytearray(bytes.byte(...))"), which meant there was a strong
> consistency argument in having the alternate constructor on both
> types. Now that the PEP proposes the "bchr" builtin, the "fromord"
> constructors look less necessary.

tl;dr -- Sounds good to me.  I'll update the PEP.

-------

When this started the idea behind the methods that eventually came to be
called "fromord" and "fromsize" was that they would be the two possible
interpretations of "bytes(x)":

   the legacy Python2 behavior:

     >>> var = bytes('abc')
     >>> bytes(var[1])
     'b'

   the current Python 3 behavior:

     >>> var = b'abc'
     >>> bytes(var[1])
     b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
       \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
       \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
       \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
       \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
       \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
       \x00\x00'

Digging deeper the problem turns out to be that indexing a bytes object
changed:

   Python 2:

     >>> b'abc'[1]
     'b'

   Python 3:

     >>> b'abc'[1]
     98

If we pass an actual byte into the Python 3 bytes constructor it behaves
as one would expect:

     >>> bytes(b'b')
     b'b'

Given all this it can be argued that the real problem is that indexing a
bytes object behaves differently depending on whether you retrieve a single
byte with an index versus a single byte with a slice:

     >>> b'abc'[2]
     99

     >>> b'abc'[2:]
     b'c'

Since we cannot fix that behavior, the question is how do we make it more
livable?

- we can add a built-in to transform the int back into a byte:

   >>> bchr(b'abc'[2])
   b'c'

- we can add a method to return a byte from the bytes object, not an int:

   >>> b'abc'.getbyte(2)
   b'c'

- we can add a method to return a byte from an int:

   >>> bytes.fromint(b'abc'[2])
   b'c'

Which is all to say we have two problems to deal with:

- getting bytes from a bytes object
- getting bytes from an int

Since "bytes.fromint()" and "bchr()" are the same, and given that
"bchr(ordinal)" mirrors "chr(ordinal)", I think "bchr" is the better
choice for getting bytes from an int.

For getting bytes from bytes, "getbyte()" and "iterbytes" are good choices.

> Given that, and the uncertain deprecation time frame for accepting
> integers in the main bytes and bytearray constructors, perhaps both
> the "fromsize" and "fromord" parts of the proposal can be deferred
> indefinitely in favour of just adding the bchr() builtin?

Agreed.

--
~Ethan~


More information about the Python-Dev mailing list