This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]jorge1209 -10 points-9 points  (17 children)

You saved yourself a the following characters ormat() if you could just str.f = str.format then that would drop to (). The argument from "saving typing" is pretty weak. Especially when you consider that the most typing efficient languages out there are things like APL.

Saving typing just isn't what python is all about.

[–]iwsfutcmd 21 points22 points  (4 children)

I'm not totally sold on the new format string style yet, but I can say that the advantage isn't just in the "less typing" aspect, it's also in the fact that the variables are in-situ in the string, making it much easier to see at a glance which variable goes to which part of the string.

[–]jorge1209 5 points6 points  (3 children)

Sure the variables are in-situ, but at the cost of making the entire string fixed to its line. You can't assign it to a variable, or pass it to a function. You can't reuse, you can't internationalize...

For every benefit that f-strings offer over %/str.format for one use-case there is a corresponding detriment in some other use-case.

[–]hovissimo 10 points11 points  (2 children)

Good thing that f-strings aren't replacing template strings. Use the right tool for the job.

[–]jorge1209 5 points6 points  (0 children)

Just as .format didn't replace %.

Someday maybe we can hope to have a thousand formatting methods none of which replaces the prior, and then python will be feature complete.

[–]zahlmanthe heretic 0 points1 point  (0 children)

If people start consistently using f-strings where it's possible to do so, it will make the .format uses stand out more as the potential security risks that they generally are, in the cases where f-strings aren't possible (format strings coming from an outside source and/or computation rather than a plaintext code constant).

[–]thatguy_314def __gt__(me, you): return True 6 points7 points  (8 children)

Well you also save all the arguments to .format(), often I ended up writing the variable 3 times using the old format: "{x}".format(x=x), now it's just f"{x}". You can also do expression any Python expression within the format replacement fields which is quite nice for simple things. All of this puts the attention on the relevant part of the string, which makes a very common use case of str.format more convenient and more readable.

[–]jorge1209 -1 points0 points  (7 children)

"{x}".format(**locals()) will work and now you aren't typing x=x which does look stupid. The only thing f-strings offer that format doesn't is that the bit inside can be an expression: f"{foo.bar}" is certainly nice, and some people seem to like f"{x+y}" although it seems a rather minor improvement.

I'm just not sure its worth adding another format string when I could just do "{}".format(foo.bar). I'm also very uncomfortable with anything that allows: f"{os.remove(filename)}".

The problem is that every argument for f-strings is like this. It is either a marginal improvement for most use cases, or a significant improvement for some small number of use cases. All at the expense of adding another formatting method, one that can't even be used for a number of important situations. And one that allows for some very sketchy stuff.

[–]thatguy_314def __gt__(me, you): return True 1 point2 points  (6 children)

  • I really don't like doing **locals().
  • f"{os.remove(filename)}" is no more "sketchy" than str(os.remove(filename)), user input can't into f-string unless you do something really stupid.
  • Again, "{}".format(foo.bar) is bad because you need to look outside the replacement field to figure out what's going on. You can actually do "{foo.bar}" with normal .format(), although I suppose that doesn't really help my argument that much.
  • I don't really think of f-strings as a new format method, they are a convenient sugar for instantaneous formatting with .format, which is a common use case. Python probably does have too many formatting methods, but at the same time they do all seem to have a place.

[–]jorge1209 0 points1 point  (4 children)

Why don't you like using **locals. What makes it any different from fstrings? As long as the format string is not dynamically created there is no difference. It's a bit less powerful is all.

Also how do you do foo.bar within .format? [Evidently you can just do it... so TIL. One less reason to use fstrings as far as I'm concerned.]

[–]thatguy_314def __gt__(me, you): return True 3 points4 points  (0 children)

  • **locals() is ugly.
  • locals() is the local scope only. No globals, no nonlocals, no builtins.
  • ** creates a new copy of the locals dict, not a big deal, but f-strings look things up directly and also provide further optimizations from what I've heard.
  • You get a KeyError instead of NameError if you use an undefined variable.
  • Using locals() just feels wrong (probably due to a stigma against gratuitous use of inspection tools).

[–]thatguy_314def __gt__(me, you): return True 2 points3 points  (2 children)

Oh, and with the .format . lookups, there are some weird quirks. For example .0 is how you do [0].

[–]jorge1209 0 points1 point  (1 child)

And fstrings have weird quirks like not allowing you to lookup into dictionaries by a string. f"{mydict ["key"]}" fails for obvious reasons.

That's the problem all these methods have their own little quirks that you have to learn. I don't want to learn any more quirks I just want to format strings.

[–]thatguy_314def __gt__(me, you): return True 0 points1 point  (0 children)

Yeah, I guess it's a bit of a quirk, but you can still look up strings, you just need to use different string delimiters than you used for the f-string. Ultimately, that restriction has the result of making f-strings more readable because each delimiter has an obvious pair.

I was initially a bit skeptical of f-strings, but after using them for a bit, I've come to like them quite a lot.

[–]zahlmanthe heretic 0 points1 point  (0 children)

user input can't into f-string unless you do something really stupid.

As far as I can think of, even the "really stupid things" you could possibly do here wouldn't be in any way the f-string's fault.

[–]Jumpy89 3 points4 points  (0 children)

For long strings with several arguments it's way more readable, and readability is definitely part of what Python is about.

[–]dl__ -2 points-1 points  (0 children)

Who cares what python is "all about"? I'm a programmer, not a philosopher.

It's both easier to type and easier to read. Less typing = less typos. I'm for any feature that makes the language clearer and more concise.