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}.

_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to