Weak Type Ability for Python

avi.e.gross at gmail.com avi.e.gross at gmail.com
Thu Apr 13 01:38:58 EDT 2023


Given the significant number of languages other than Python that have some
version of a feature that allows implicit conversion of unlike operands to
concatenate something like a "number" and a string into a string, the
question may not be silly as to how or why Python chose as it chose.

As I see it, python did put in quite a bit of customizability and
flexibility including the ability to create your own object types that alter
the behavior of an operator like plus. I have seen plenty of code that takes
advantage and makes the user of the code assume that different types can
interact seamlessly.

But it is like many other things. Languages that support a wide variety of
integer types such as signed and unsigned versions of integers in 8 bits,
sixteen bits, 32 bits and even 64 bits or perhaps higher, will often look
like they allow you to mix them in various combinations for not just
addition. But underneath it all can be lots of hidden complexity. I have
seen languages that make lots of functions with the same names but different
signatures and then dispatch a call like add(int8, unsignedint32) to the
right function that best matches their signature. The functions internally
can do many things but often convert their arguments to a common format,
perform the operations, then perhaps convert back to whatever result output
was expected.

In the case being discussed we might have to create something that looks
like do_plus(int, int) and then do_plus(int, char) and so on.

The other alternatives can include tables of "generality" and
"convertibility" with rules that govern how to perform a calculation by
changing or upgrading or downgrading things to make a match that can then be
handled. 

The issue here is a sort of operator overloading. In Python, "+" does not
mean plus at all. It means whatever the programmer wanted it to mean. An
infix line of code that includes "obj1 + obj2" is supposed to investigate
how to do it. I am not sure if some built-in objects may be different, but
it does a sequence of operations till it finds what it needs and does it.

I believe it looks a bit like this. The LHS object, obj1, is examined to see
if it has defined a __add__() method. If found, it is called and either
produces a result or signals it cannot handle obj2 for some reason. If that
method is not found, or fails, then it looks to see if the RHS, obj2, has a
__radd__() method defined. That can be given obj1 and return an answer or
signal failure. 

If obj1 is 5 and obj2 is "pm" then we are using the built-in predefined
classes that currently have no interest in concatenating or adding unlike
types like this. If you could add or change these dunder methods (and note
you may also need to deal with __iadd__() to handle the case where x=5 and
you write "x += "pm" albeit that could weirdly change the type of x without
a linter having a clue.

I suggest the latter argument may be a good enough reason that Python did
not implement this. There are many good reasons. Does anyone like a language
that lets you type 2 + "three" and quietly makes that be 5? Sure, it can be
made to work on a subset of number in say English, but will it work in other
languages. It can be hard enough now to write code in UNICODE (I have seen
some) that tries to determine if a code point represents a number in some
language or representation and treats it as a numeral. I have seen the
numeric bullets such as a dark circle containing a white nine be treated as
if the user had put in a nine, for example.

As was mentioned, some languages have different operators for addition
versus concatenation and in that context, it may be intuitive that using the
wrong object type is an implicit call to conversion. Python uses "+" for
both purposes depending on context and potentially for many more purposes
the programmer can devise. 

Consider the asterisk operator as a companion concept. It gladly accepts a
string and a number in either order and does something somewhat intuitive
with them by treating multiplication as a sort of repeated addition:

>>> 5 * "6"
'66666'
>>> "5" * 6
'555555'
>>> 3 * "Hello? "
'Hello? Hello? Hello?

But it will not handle float.

>>> "Hello" * 2.5
TypeError: can't multiply sequence by non-int of type 'float'

If you want to either truncate a float to an into or round it or take a
ceiling, though, it will not guess for you and you must do something
explicit like this:

>>> "Hello" * round(2.5)
'HelloHello'
>>> "Hello" * round(2.6)
'HelloHelloHello'
>>> "Hello" * int(2.6)
'HelloHello'

There is a parallel argument here in arguing it should accept a float and
truncate it. But since you can easily cast a float to an int, in any of many
ways, why have the program choose when it quite likely reflects an error in
the code. And, no, I do not suggest 2.5 be interpreted as putting in an
approximate percentage so that .8 * "Hello" should result in "Hell" ...




-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com at python.org> On
Behalf Of Cameron Simpson
Sent: Wednesday, April 12, 2023 11:43 PM
To: python-list at python.org
Subject: Re: Weak Type Ability for Python

On 13Apr2023 03:36, MRAB <python at mrabarnett.plus.com> wrote:
>I thought that in Java you can, in fact, concatenate a string and an 
>int, so I did a quick search online and it appears that you can.

I stand corrected. I could have sworn it didn't, but it has been a long 
time. - Cameron Simpson <cs at cskk.id.au>
-- 
https://mail.python.org/mailman/listinfo/python-list



More information about the Python-list mailing list