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
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
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
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- Andrey Popp phone: +7 911 740 24 91 e-mail: 8mayday@gmail.com
On 2010-07-23, at 14:26 , Andrey Popp wrote:
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.
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 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.
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
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
Currently, this raises TypeError.
I think allowing implicit conversion break backward compatibility and
allowing new syntax that is now syntax error doesn't cause a
compatibility problem.
--
INADA Naoki
On Fri, 23 Jul 2010 08:35:40 -0400
Alex Light
On Fri, Jul 23, 2010 at 8:26 AM, Andrey Popp <8mayday@gmail.com> wrote:
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.
It also violates TOOOWTDI.
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
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.
On 2010-07-23, at 15:05 , Mike Meyer wrote:
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. Actually, it's much simpler than that for Java: the `+` operator is specially overloaded any time a string is involved to become a "convert and concatenate" operator similar to PHP's "." rather than the usual "add" operator.
In Python, the equivalent behavior would be to special case the addition operator so that it checks if either operand is a string and if it is convert and concatenate the other one, otherwise apply normal resolution.
On Fri, 23 Jul 2010 15:25:42 +0200
Masklinn
On 2010-07-23, at 15:05 , Mike Meyer wrote:
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. Actually, it's much simpler than that for Java: the `+` operator is specially overloaded any time a string is involved to become a "convert and concatenate" operator similar to PHP's "." rather than the usual "add" operator.
In Python, the equivalent behavior would be to special case the addition operator so that it checks if either operand is a string and if it is convert and concatenate the other one, otherwise apply normal resolution.
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.
On 2010-07-23, at 15:37 , Mike Meyer wrote:
On Fri, 23 Jul 2010 15:25:42 +0200 Masklinn
wrote: On 2010-07-23, at 15:05 , Mike Meyer wrote:
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. Actually, it's much simpler than that for Java: the `+` operator is specially overloaded any time a string is involved to become a "convert and concatenate" operator similar to PHP's "." rather than the usual "add" operator.
In Python, the equivalent behavior would be to special case the addition operator so that it checks if either operand is a string and if it is convert and concatenate the other one, otherwise apply normal resolution.
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. There isn't really such a thing as "the string version of +" as Java forbids userland operator overloading. String's + is a special case in the language as it is, indeed, one of the very few (if not the only) overloaded operator.
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)`
In python, that would be making str.__add__ (and friends) do the conversion. You'd run into the issues of writing `a + "foo"` with `a` defining a custom `__add__`, which would not perform string concatenation, as per Python's operator resolution order.
[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
On 2010-07-23, at 15:37 , Mike Meyer wrote:
On Fri, 23 Jul 2010 15:25:42 +0200 Masklinn
wrote: On 2010-07-23, at 15:05 , Mike Meyer wrote:
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. Actually, it's much simpler than that for Java: the `+` operator is specially overloaded any time a string is involved to become a "convert and concatenate" operator similar to PHP's "." rather than the usual "add" operator.
In Python, the equivalent behavior would be to special case the addition operator so that it checks if either operand is a string and if it is convert and concatenate the other one, otherwise apply normal resolution.
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. There isn't really such a thing as "the string version of +" as Java forbids userland operator overloading. String's + is a special case in the language as it is, indeed, one of the very few (if not the only) overloaded operator.
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)`
In python, that would be making str.__add__ (and friends) do the conversion. You'd run into the issues of writing `a + "foo"` with `a` defining a custom `__add__`, which would not perform string concatenation, as per Python's operator resolution order.
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.
On 2010-07-23, at 16:09 , Mike Meyer wrote:
In python, that would be making str.__add__ (and friends) do the conversion. You'd run into the issues of writing `a + "foo"` with `a` defining a custom `__add__`, which would not perform string concatenation, as per Python's operator resolution order.
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.
Right. Because otherwise it should not be very hard (which doesn't mean it would be smart) to remove the type error from str.__add__ and str.__radd__ and just str() the argument if it isn't already a string.
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
On Fri, Jul 23, 2010 at 11:16 AM, INADA Naoki
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:
[snip]
What's wrong with s = 'foo' + str(bar) + 'baz' If you want something Pythonic: import this ... Explicit is better than implicit --- André
On 2010-07-23, at 16:16 , INADA Naoki wrote:
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.
I don't understand what you find messy about either this or `'foo{}baz'.format(bar)`.
* 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.
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.
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.
If you want something Pythonic:
import this ... Explicit is better than implicit
--- André
Thank you.
--
INADA Naoki
On Sat, Jul 24, 2010 at 2:06 AM, Masklinn
On 2010-07-23, at 16:16 , INADA Naoki wrote:
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.
I don't understand what you find messy about either this or `'foo{}baz'.format(bar)`.
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.
* 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.
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.
I agree with you.
--
INADA Naoki
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.
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. ;)
On 7/23/10 3:26 PM, Dag Odenhall 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.
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)
Or use: text = '...{context.name}...'.format(context=context) This is a great trick when "context" is "self". -- Eric.
participants (8)
-
Alex Light
-
Andre Roberge
-
Andrey Popp
-
Dag Odenhall
-
Eric Smith
-
INADA Naoki
-
Masklinn
-
Mike Meyer