String interpolation again.

Hi, all. Below code is syntax error now: foo = 123 x = 'foo' foo 'bar' I wonder if that code is interpreted as: x = 'foo' + str(foo) + 'bar' or x = 'foo%sbar' % (foo,) I think this syntax sugar doesn't import any compatibility problem and simple enough for Python. What do you think about it? -- INADA Naoki <songofacandy@gmail.com>

I think it's a form of weak typing from languages like PHP, that allows programmer to make huge amounts of mistakes, that are sometimes difficult to spot. On Fri, Jul 23, 2010 at 4:10 PM, INADA Naoki <songofacandy@gmail.com> wrote:
-- Andrey Popp phone: +7 911 740 24 91 e-mail: 8mayday@gmail.com

On 2010-07-23, at 14:26 , Andrey Popp wrote:
For what it's worth, even PHP doesn't allow this. One either has to concatenate "foo" . $foo . "bar" or interpolate "foo${foo}bar" The only language I am aware of which *might* let users do something along those lines (please note that I'm not even sure it's possible) would be Tcl, in which pretty much everything seems to be a string.

On Fri, Jul 23, 2010 at 8:26 AM, Andrey Popp <8mayday@gmail.com> wrote:
I agree. but i wouldn't mind if python would start automatically calling str on objects in string sequences if they are not strings. i.e. turn this not_a_string = 123 a_string = 'this is a string' + not_a_string #currently throws syntax error to this: a_string = 'this is a string ' + str(not_a_string) they do this in java and it works quite well Alex

On Fri, 23 Jul 2010 08:35:40 -0400 Alex Light <scialexlight@gmail.com> wrote:
It also violates TOOOWTDI.
I believe the initial quote applies to this form as well. It might work well in Java, but Java isn't Python; there are lots of other differences that make this a lot more tolerable in Java. The first problem with this kind of thing is that there's no obvious reason why 12 + '34' should be '1234' instead of 46. Java variables have declared types. This means the above situation can be detected at compile time, and the implicit conversion added then. In Python, you have to do the tests at run time, which will slow everything down. Further, Java's typed variables means that if you've made a mistake in the type of one of the values, the assignment will be flagged as an error at compile time. Python won't do that, so implicitly fixing the mistake here means you get even further from the error before something happens that reveals it. Finally, the % operator does that implicit conversion for you if you use %s: a_string = 'this is a string %s' % not_a_string Works just fine as things are now (though the syntax needs tweaking if not_a_string is a tuple). I think brings it to -4. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

On Fri, 23 Jul 2010 15:25:42 +0200 Masklinn <masklinn@masklinn.net> wrote:
I would hope the Java version isn't as convoluted as you say (but given Java, it may be): all this really requires is that the string version of + include the conversion. In python, that would be making str.__add__ (and friends) do the conversion. Given that in Python, str(a_string) is a_string, and doing the type check on a string (via either type or isinstance) is about the same speed as calling str on it (just under .2 usecs/loop), you might as well just always do the conversion. Or maybe this breaks unicode... Assuming, of course, you actually think this is a good idea. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

On 2010-07-23, at 15:37 , Mike Meyer wrote:
To understand how far this goes, Java's BigInteger (their equivalent to Python's long) doesn't have *any* operator overloading. If a is a BigInteger and b is a BigInteger, you add them by writing `a.add(b)`. Likewise for substraction, multiplication, division, negation or bit-twiddling[0] And if either is *not* a BigInteger, then you convert it to a BigInteger first. If it's a primitive integer type, you cannot even use a constructor, you have to use `BigInteger.valueOf(long)`
[0] http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/math/Big...

On Fri, 23 Jul 2010 15:50:26 +0200 Masklinn <masklinn@masklinn.net> wrote:
That's what the "and friends" is for. str.__radd__ is one of the friends. If the type of a refused to do the add, then str.__radd__ would get it, and could do the conversion and concatenation. Of course, if the type of a did the add in some way *other* than via the conversion and concatenation, then that's what would happen. Which is one of the reasons this type of implicit conversion isn't right for Python. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

Basic problem is Python doesn't provide a way to print values of expression into str like print prints to file. 'foo{bar}baz'.format(bar=bar) is a bit bessy. ’foo{bar}baz'.format(**vars()) or other technique is a bit trickey and messy. If s = 'foo' bar 'baz' is too dirty, another Pythonic way I think of are: * s = str('foo', bar, 'baz') This is not compatible current Python because str()'s second argument is encoding and third argument is error handler. I think Python4 should not accept str(a_bytes, 'utf-8') and use a_bytes.decode('utf-8') * s = print('foo', bar, 'baz', sep='', file=None) * s = print('foo', bar, 'baz', sep='', file=str) Extend print() function to return str instead of print to file. * s = str.print('foo', bar, 'baz', sep='') Add staticmethod to str. -- INADA Naoki <songofacandy@gmail.com>

What's wrong with s = 'foo' + str(bar) + 'baz'
OK, I agree that your code is very pythonic. I've seen and wrote some PHP and Ruby code today, so I've forgotten what's pythonic. Many people from PHP/Ruby/Perl look at string interpolation and find .format(**vars()) trick and feel it's messy. But if there is a clean and pythonic way, adding new syntax is not pythonic.
Thank you. -- INADA Naoki <songofacandy@gmail.com>

On 2010-07-23, at 16:16 , INADA Naoki wrote:
I don't understand what you find messy about either this or `'foo{}baz'.format(bar)`.
These forms can trivially be implemented as utility functions. And I don't see them as improvements enough to propose them for inclusion in the stdlib, but YMMV.

On Sat, Jul 24, 2010 at 2:06 AM, Masklinn <masklinn@masklinn.net> wrote:
In my code, '{bar}' and 'bar=bar' seems too verbose. Your code is simple when the literal is short, but it is difficult to check which variable is inserted where when string is long.
I agree with you. -- INADA Naoki <songofacandy@gmail.com>

format = '...{short_descriptive_name}...' text = format.format( short_descriptive_name=long_cumbersome_variable_name, other_name=other_name, ...) Don't be afraid of more lines of code if it helps readability. You could also build a context dict: context = {} context['name'] = complicated_code_to_get_name() ... text = '...{name}...'.format(**context) Of course personally I want a where/given clause, but that's a different thread. ;)

I think it's a form of weak typing from languages like PHP, that allows programmer to make huge amounts of mistakes, that are sometimes difficult to spot. On Fri, Jul 23, 2010 at 4:10 PM, INADA Naoki <songofacandy@gmail.com> wrote:
-- Andrey Popp phone: +7 911 740 24 91 e-mail: 8mayday@gmail.com

On 2010-07-23, at 14:26 , Andrey Popp wrote:
For what it's worth, even PHP doesn't allow this. One either has to concatenate "foo" . $foo . "bar" or interpolate "foo${foo}bar" The only language I am aware of which *might* let users do something along those lines (please note that I'm not even sure it's possible) would be Tcl, in which pretty much everything seems to be a string.

On Fri, Jul 23, 2010 at 8:26 AM, Andrey Popp <8mayday@gmail.com> wrote:
I agree. but i wouldn't mind if python would start automatically calling str on objects in string sequences if they are not strings. i.e. turn this not_a_string = 123 a_string = 'this is a string' + not_a_string #currently throws syntax error to this: a_string = 'this is a string ' + str(not_a_string) they do this in java and it works quite well Alex

On Fri, 23 Jul 2010 08:35:40 -0400 Alex Light <scialexlight@gmail.com> wrote:
It also violates TOOOWTDI.
I believe the initial quote applies to this form as well. It might work well in Java, but Java isn't Python; there are lots of other differences that make this a lot more tolerable in Java. The first problem with this kind of thing is that there's no obvious reason why 12 + '34' should be '1234' instead of 46. Java variables have declared types. This means the above situation can be detected at compile time, and the implicit conversion added then. In Python, you have to do the tests at run time, which will slow everything down. Further, Java's typed variables means that if you've made a mistake in the type of one of the values, the assignment will be flagged as an error at compile time. Python won't do that, so implicitly fixing the mistake here means you get even further from the error before something happens that reveals it. Finally, the % operator does that implicit conversion for you if you use %s: a_string = 'this is a string %s' % not_a_string Works just fine as things are now (though the syntax needs tweaking if not_a_string is a tuple). I think brings it to -4. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

On Fri, 23 Jul 2010 15:25:42 +0200 Masklinn <masklinn@masklinn.net> wrote:
I would hope the Java version isn't as convoluted as you say (but given Java, it may be): all this really requires is that the string version of + include the conversion. In python, that would be making str.__add__ (and friends) do the conversion. Given that in Python, str(a_string) is a_string, and doing the type check on a string (via either type or isinstance) is about the same speed as calling str on it (just under .2 usecs/loop), you might as well just always do the conversion. Or maybe this breaks unicode... Assuming, of course, you actually think this is a good idea. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

On 2010-07-23, at 15:37 , Mike Meyer wrote:
To understand how far this goes, Java's BigInteger (their equivalent to Python's long) doesn't have *any* operator overloading. If a is a BigInteger and b is a BigInteger, you add them by writing `a.add(b)`. Likewise for substraction, multiplication, division, negation or bit-twiddling[0] And if either is *not* a BigInteger, then you convert it to a BigInteger first. If it's a primitive integer type, you cannot even use a constructor, you have to use `BigInteger.valueOf(long)`
[0] http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/math/Big...

On Fri, 23 Jul 2010 15:50:26 +0200 Masklinn <masklinn@masklinn.net> wrote:
That's what the "and friends" is for. str.__radd__ is one of the friends. If the type of a refused to do the add, then str.__radd__ would get it, and could do the conversion and concatenation. Of course, if the type of a did the add in some way *other* than via the conversion and concatenation, then that's what would happen. Which is one of the reasons this type of implicit conversion isn't right for Python. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

Basic problem is Python doesn't provide a way to print values of expression into str like print prints to file. 'foo{bar}baz'.format(bar=bar) is a bit bessy. ’foo{bar}baz'.format(**vars()) or other technique is a bit trickey and messy. If s = 'foo' bar 'baz' is too dirty, another Pythonic way I think of are: * s = str('foo', bar, 'baz') This is not compatible current Python because str()'s second argument is encoding and third argument is error handler. I think Python4 should not accept str(a_bytes, 'utf-8') and use a_bytes.decode('utf-8') * s = print('foo', bar, 'baz', sep='', file=None) * s = print('foo', bar, 'baz', sep='', file=str) Extend print() function to return str instead of print to file. * s = str.print('foo', bar, 'baz', sep='') Add staticmethod to str. -- INADA Naoki <songofacandy@gmail.com>

What's wrong with s = 'foo' + str(bar) + 'baz'
OK, I agree that your code is very pythonic. I've seen and wrote some PHP and Ruby code today, so I've forgotten what's pythonic. Many people from PHP/Ruby/Perl look at string interpolation and find .format(**vars()) trick and feel it's messy. But if there is a clean and pythonic way, adding new syntax is not pythonic.
Thank you. -- INADA Naoki <songofacandy@gmail.com>

On 2010-07-23, at 16:16 , INADA Naoki wrote:
I don't understand what you find messy about either this or `'foo{}baz'.format(bar)`.
These forms can trivially be implemented as utility functions. And I don't see them as improvements enough to propose them for inclusion in the stdlib, but YMMV.

On Sat, Jul 24, 2010 at 2:06 AM, Masklinn <masklinn@masklinn.net> wrote:
In my code, '{bar}' and 'bar=bar' seems too verbose. Your code is simple when the literal is short, but it is difficult to check which variable is inserted where when string is long.
I agree with you. -- INADA Naoki <songofacandy@gmail.com>

format = '...{short_descriptive_name}...' text = format.format( short_descriptive_name=long_cumbersome_variable_name, other_name=other_name, ...) Don't be afraid of more lines of code if it helps readability. You could also build a context dict: context = {} context['name'] = complicated_code_to_get_name() ... text = '...{name}...'.format(**context) Of course personally I want a where/given clause, but that's a different thread. ;)
participants (8)
-
Alex Light
-
Andre Roberge
-
Andrey Popp
-
Dag Odenhall
-
Eric Smith
-
INADA Naoki
-
Masklinn
-
Mike Meyer