4 ms·
I am against it, because it allows arbitrary Python expressions inside format strings. It's too complicated and lets user have two different ways of doing thing
by asgard1024 11y ago
I am against it, because it allows arbitrary Python expressions inside format strings. It's too complicated and lets user have two different ways of doing things (not Pythonic) - one to calculate expression inside string and the other to calculate it outside (which should IMHO be preferred). This should maybe go to the standard library, but please not into the language.
I think a better approach would be to just add special formatter operators (if they aren't already there) that would just call str() or repr() or ascii() to whatever is presented to them (and maybe take some optional arguments such as length or padding).
- task_queue 11y ago> I am against it, because it allows arbitrary Python expressions inside format strings. I was for this PEP until your post made this reality apparent. I'll take security over convenience.
- imakesnowflakes 11y agoI will go further and say that I will even take readability over convenience. This is a step in the reverse direction. Please don't do this. I am not sure why this is even considered. We already have ways to do this clearly. Let us not add another way to do this in a less readable way that is a lot more easier to write. That is a deadly combination. Features in python are geared towards more readable code (I know about the stuff you can do with things like comprehensions, but hey I think their power justifies them enough). This will lead to people using this format due to initial convenience, but ends up regretting doing so. Please remember that code is read more often than it is written. So a requiring a little verbosity if that can enhance readability even a little bit, is good. I hope these kinds of good things about python does not get removed. I am coming from 9 years of experience with PHP. And I will say that this is not worth it. And this is actually one of the features I have come to like in Python now. And that is not considering the implications of having expression evaluation inside strings...
- mkesper 11y agoI actually think the proposal would be more readable because you don't have to think about what it means. Compare: "{} of very long text here...".format(value) f"{value} of very long text here..."
- imakesnowflakes 11y agoI thinks this is where our difference in comes from. When we are reading code, we are not usually reading the strings contained within. We are reading variables names, we are looking at where they are used, where they are assigned, stuff like that. I very rarely look inside the strings when we are actually reading code. When reading code, strings are just black boxes where nothing can happen. So we can completely ignore them. With this pep, that will change. And readability takes a big hit. Strings are no longer black boxes. And actually you can get the " {value} if very long text" format right now using the format function, but it right now requires an explicit list/dictionary of variables. This explicit list of variables really helps in the context of reading code. And forcing users to write down that explicit list of variables to use, is good.
- Camillo 11y agoHow do you know where the string ends? If your editor has syntax coloring and you look for the end of the string-color block, then the expressions inside the string will also have a different color and will pop right out. If you don't use syntax coloring you have to scan for " or ', and you'll learn to scan for { too.
- imakesnowflakes 11y ago>How do you know where the string ends? I usually just go to the end of the line. or if that is not possible, I think I usually look at the next closest thing that obviously is not a string and scan backwards. I mean, usually I didn't have to do anything consciously (or do a scan) to spot the end of a string.
- 11y ago
- voyou 11y agoI don't think this is actually a security concern. The only place f-strings are evaluated is where they're directly included in the source; they can't be supplied by a user (unless you're using "eval," in which case the security concern applies with or without f-strings). As the PEP says: "Because the f-strings are evaluated where the string appears in the source code, there is no additional expressiveness available with f-strings. There are also no additional security concerns: you could have also just written the same expression, not inside of an f-string."
- task_queue 11y agoShould have read the PEP in full. Thanks : )
- ceronman 11y agoThis proposal doesn't affect security in any way. It's just syntactic sugar. Instead of writing this: 'My name is ' + format(name) + ' my age next year is ' + format(age+1) or 'My name is {name}, my age next year is {age}'.format(name=name, age=age+1) You just write f'My name is {name}, my age next year is {age=1}' It's shorter, it's more readable and more convenient. I can't wait for this PEP to be accepted. Edit: Fixed small errors in the examples.
- imakesnowflakes 11y agoFirst of all, I don't think you can do {age+1} in a string right now. But you can use string placeholders when used with format function. That should take take of this use case. So no need to add another syntactic sugar to make it more convenient. It is already as simple as possible. Let us not try to simplify it further. I will be horrified and very worried about the direction that the language has taken if this pep gets accepted.
- ceronman 11y agoYou're right, you can't do {age+1} in a string right now. I just edited to fix it.
- sanderjd 11y agoThis perspective is so interesting to me. You say the version using `.format` is "as simple as possible", but the interpolated version seems clearly simpler to me, because it eliminates the redundancy in the placeholders. What's the disconnect here?
- imakesnowflakes 11y ago> but the interpolated version seems clearly simpler to me. What's the disconnect here? The disconnect is this. An explicit list of variables to use for interpolation is not redundancy. Because the placeholders does not, by themselves, refer to anything. Placeholders are just holes and only have a meaning in the context of formatting functions. And even in them, they does not refer to a local variables, even when they share a common name. So when you use .format() function, you are actually saying, "here is a string with some named holes. Fill the hole named 'A' with the value from variable 'A', the hole named 'B' with the value from variable 'B'. So hole 'A' and variable 'A' are different things even if they share the same name. Now, the simplicity argument. Every thing should be made as simple as possible. But not simpler. Why not? Because when you simplify further, you are paying a cost (often not apparent initially), some times in clarity, sometimes in correctness and so on. The pigeonhole principle. In our case, we can further simplify the process by adding an implicit mapping from named placeholders to local variables. When you do so, you are adding something implicit. The costs of which might not be apparent at this point.. So this pep is strapping on something to the whole language, to slightly simplify this one use case. Which is why I said that it is trying to simplify it further than it is possible.
- jerf 11y agoI'd submit the security concern is more that specifying a string interpolation format without first-class thought about how to encode interpolated strings is a terrible idea in 2015, and people need to really stop doing this. See http://www.jerf.org/iri/post/2942 http://www.jerf.org/iri/post/2942 and the example library I use to demonstrate the point, https://github.com/thejerf/strinterp https://github.com/thejerf/strinterp . Of course all current methods of string interpolation in Python have that problem too. And typing that sentence really, really makes we want to link http://xkcd.com/927/ http://xkcd.com/927/ . I'm unconvinced adding a fourth choice at this very late date can fix anything.
- CJefferson 11y agoNote that these format strings must exist in the source code -- you can't read them from the user then execute it.
- digisign 11y agoIt's an industry std now, can't put it in a lib without extra syntax.
- baq 11y agodisagree. it only allows Python expressions in the same context in which they are already allowed: in the code. it's not possible to create an f-string at runtime.
- asgard1024 11y agoSecurity was not my primary concern, but even if the design can be made secure, it is still a concern (because bugs happen). In any case, you just stated another counter argument - it breaks orthogonality of the language (string being interpolated must be a literal), just to make one assignment not explicit. Maybe it is popular in other languages - their call, but the fact is, it goes quite wildly against Python design philosophy. I would also like to note that the are templating systems that let you evaluate arbitrary Python expressions. Perhaps these would be a better choice for users who feel need for this proposal.
- baq 11y agoi agree that there are multiple templating solutions, but i disagree that they fill the same niche. this is a language usability (UX even) thing, not a purity thing. the fact is people do '...'.format(locals()) for the same purpose (or '...' % locals()), which is strictly worse and may not even work on some python implementations. i also disagree that this feature goes against the zen of python: practicality beats purity, after all.
- Camillo 11y ago> I am against it, because it allows arbitrary Python expressions inside format strings. As well it should. Programming language features should be orthogonal as much as possible. > It's too complicated and lets user have two different ways of doing things (not Pythonic) - one to calculate expression inside string and the other to calculate it outside (which should IMHO be preferred). You must hate expression nesting, then. Look at all these ways of doing the same thing: x = a + b * (c - d) e = c - d x = a + b * e f = b * (c - d) x = a + f e = c - d f = b * e x = a + f Clearly, expressions should be restricted to no more than one binary operator. That reduces the number of different ways of computing the expression, and forces the programmer to give a name to each sub-step, which enhances readability, clarity, and debugging-friendliness. I feel dirty just for having written that.
- asgard1024 11y agoThis is a straw man. If you want to evaluate expressions inside a long string, you can as easily write: "The sum of a and b is " + (a+b) + "!" This is completely analogous to your examples. The only disadvantage of this method is the extra quotes, but that's just syntax. You could think that having the literal string split is a disadvantage, but it really isn't - since in the proposal the string has to be literal anyway, so in either case it cannot be a variable. In general, in what I would consider good language design (syntactic-wise), you either interpret expressions by default and then quote string literals (like most languages do), or you interpret literals by default and then quote expressions (this is the method regular expressions language, or templating languages, use). But you shouldn't do both, it's just a can of worms, especially for code highlighting tools (although in a language with Lisp-like design philosophy - which Python is not - why not, you can do it today with reader macros and whatnot).
- sanderjd 11y agoI'm curious if you've ever spent a lot of time using a language that has a solution similar to the proposal, for instance Ruby, or the newer JavaScript versions. All of the theoretical stuff about good syntax design and code highlighting cans of worms rings incredibly hollow to me in the face of how fundamentally nicer this sort of syntax is. It's the first thing I forget Python doesn't have after not using it for awhile, which I then go looking for, and once again find myself surprised at its absence. I also find the "un-Pythonic to have more than one way to do it" argument interesting, as there seem to be three approaches to string formatting in idiomatic use in Python (`.format`, `%`, and string concatenation), whereas in Ruby, the direct interpolation approach is used nearly exclusively. You do lose type-checking capabilities by giving up format specifiers (which, for instance, Rust checks at compile-time), but Python can't take much advantage of that to begin with.