[Python-ideas] More alternate constructors for builtin type

Serhiy Storchaka storchaka at gmail.com
Mon May 6 03:49:35 EDT 2019


Constructors for builtin types is too overloaded.

For example, int constructor:

* Converts a number (with truncation) to an integer.
* Parses human readable representation of integer from string or 
bytes-like object. Optional base can be specified. Note that there is an 
alternate constructor for converting bytes to int using other way: 
int.frombytes().
* Without arguments returns 0.

str constructor:

* Converts an object to human-readable representation.
* Decodes a bytes-like object using the specified encoding.
* Without arguments returns an empty string.

bytes constructor:

* Converts a bytes-like object to a bytes object.
* Creates a bytes object from an iterable if integers.
* Encodes a string using the specified encoding. The same as str.encode().
* Creates a bytes object of the specified length consisting of zeros. 
Equals to b'\0' * n.

dict constructor:

* Creates a dict from a mapping.
* Creates a dict from an iterable of key-value pairs.
* Without arguments returns an empty dict.

The problem of supporting many different types of input is that we can 
get wrong result instead of error, or that we can get error later, far 
from the place where we handle input.

For example, if our function should accept arbitrary bytes-like object, 
and we call bytes() on the argument because we need the length and 
indexing, and we pass an integer instead, we will get an unexpected 
result. If our function expects a number, and we call int() on the 
argument, we may prefer to get an error if pass a string.

I suggest to add limited versions of constructors as named constructors:

* int.parse() -- parses string or bytes to integer. I do not know 
whether separate int.parsestr() and int.parsebytes() are needed. I think 
round(), math.trunc(), math.floor() and math.ceil() are enough for lossy 
converting numbers to integers. operator.index() should be used for 
lossless conversion.
* bytes.frombuffer() -- accepts only bytes-like objects.
* bytes.fromvalues() -- accepts only an iterable if integers.
* dict.frommapping() -- accepts only mapping, but not key-value pairs. 
Uses __iter__() instead of keys() for iterating keys, and can take an 
optional iterable of keys. Equals to {k: m[k] for k in m} or {k: m[k] 
for k in keys}.
* dict.fromitems() -- accepts only key-value pairs. Equals to {k: v for 
k, v in iterable}.



More information about the Python-ideas mailing list