4 ms·
db.execute(t"Select Count(1) from someTable") It's one extra letter to "force" for an unparameterized query over a "raw string". The t-string itself works just
by WorldMaker 2y ago
db.execute(t"Select Count(1) from someTable")
It's one extra letter to "force" for an unparameterized query over a "raw string". The t-string itself works just fine without parameters.
There's definitely a backwards compatibility hurdle of switching to a template-only API, but a template-only API doesn't look that much "less friendly" with inputs, when the only difference is a `t` before every string, regardless of number of parameters.
- crazygringo 2y agoSure, but it's just I don't have to do that anywhere else. I never put an f in front of a string if I'm not putting variables within it. And I'm generally used to Python inputs being liberal. I can usually pass a list if it expects a tuple; I can pass an int if it expects a float; often I can pass an item directly instead of a tuple with a single item. Regex functions take regular strings or regex strings, they don't force regex strings. Being forced to use a single specific type of string in all cases is just very different from how Python has traditionally operated. It's safer, I get that. But it's definitely less friendly, so I'll be curious to see how module maintainers decide to handle this.
- scott_w 2y agoEr… that’s just not correct? Python can be more liberal but it’s not always. It depends entirely on the tooling. Libraries will take time to catch up but I can definitely see people creating libraries that enforce t-strings, even if they’re deconstructing them under the hood for legacy libraries.
- crazygringo 2y agoWhat's not correct? Python inputs usually are liberal. I didn't say always. Are you claiming it's traditionally common in Python to be strict with inputs, and that being liberal is the exception?
- scott_w 2y agoThat Python lets you blindly interchange different types for no good reason. It simply doesn’t. Yes, it’s common for Python to be strict for inputs when the types are different. For example, try: Decimal(‘3.0’) / 1.5 You’ll get an error and for good reason.
- crazygringo 2y agoBut... it usually does. For example, try: Decimal('3.0') / 2 It works fine. It doesn't work with a float, which is for good reason. That's the whole point -- its general philosophy is to be pretty liberal with types, except when there's a good reason not to be. Heck, you can even do dumb things like: 4 + True And get 5 back. If that's not "blindly interchanging different types for no good reason" then I don't know what is. You can even multiply your Decimal object by False and get an answer... Or it's like my original example -- the Regex module isn't restricted to r-strings. It happily works with regular strings. Python's general philosophy is to handle input liberally. Even type hinting is an add-on. Now, it doesn't go as far as JavaScript in allowing e.g. "4"+1, but it's still awfully liberal. I just don't see how you can claim otherwise.
- scott_w 2y agoI know about Decimal/int mixing but that’s for a good reason: it’s fine to intermix here. But not for floats (precision issues). The bool/int mixing isn’t “good.” It’s a bad implementation detail that Python is stuck maintaining forever. I’m actually stunned that you think to use this as an example when I think I’d fire any programmer that did that in my team for gross negligence. The reason it works is because Python functionally has no bool type. True and False are just integers with names. It’s stupid and shouldn’t work like that but it does for historic reasons. Your example of regex makes no sense either. There is no difference between strings and r-strings. They’re literally the same thing to the interpreter, so how could the regex functions enforce you use r-strings? Maybe they should be different but, for historic reasons, they can’t be without Python 4.0.
- 2y ago
- 0cf8612b2e1e 2y agoI never put an f in front of a string if I'm not putting variables within it. Linters will even complain if you have a f string without variables. I assume it will be the same for t strings.
- davepeck 2y agoFor the reasons discussed above, I'm not sure that it will be the case for t-strings. I think it'll take a little while for frameworks/libraries to adapt (while still maintaining backward compatibility) and a while for best practices to find their way into our linting and other tools.
- 0cf8612b2e1e 2y agoIf you can use a string anywhere you can use a t-string, then a non parametrized t-string is a code smell (lining error). If there is a dedicated template-string API, then there is the implicit threat you are breaking backwards compatibility to stop using regular strings.
- davepeck 2y ago> If you can use a string anywhere you can use a t-string You can't; they're different types. t-strings are not `str` It's up to good framework/API design to take advantage of this.
- WorldMaker 2y agoYeah, "t-string" is possibly a misnomer, because they are in fact at runtime a Template object (from string.templatelib).
- 0cf8612b2e1e 2y agoA library writer ultimately has to decide if they accept both types. For a database cursor, do you take regular strings + parameter arguments and template strings? Or dedicate a new API to the idea? cursor.execute(“select * from x where foo=?”, {foo=1}) # while also allowing cursor.execute(t“select * from x where foo={foo}”) #Vs cursor.executetemplate(“select * from x where foo={foo}”) If ‘execute’ takes string and t-string, then I would consider it a problem to use a t-string without parameters. If there is a novel API just for t-strings, then you are implying widespread breaking changes as you have a schism between the two ways of providing parameters.
- WorldMaker 2y ago> Being forced to use a single specific type of string in all cases is just very different from how Python has traditionally operated. Maybe that's partly the disconnect here? "t-string" is probably a confusing colloquial name because they aren't strings, they are Templates. The runtime type is a Template. It is a very different duck-type from a string. As a duck-typable object it doesn't even implicitly or explicitly act like a string, there's intentionally no `__str__()` method and `str(someTemplate)` doesn't work like you'd expect. It shouldn't be a surprise that there is also no implicit conversion from a string and you have to use its own literal syntax: it isn't a string type, it's a Template type. Python here is still liberal with respect to Templates (it is still a duck type). If a function expects a Template and you don't want to use the t"" shorthand syntax nor use the Template constructor in string.templatelib, you just need a simple class of object that has an `__iter__()` of the correct shape and/or has `strings` and `values` tuples. Sure, it may make sense for some types of APIs to support a Union of str and Template as "liberal" options, but it's a different class of liberal support from Union of list and tuple or Union of int and float which are closer "domains" of types. A Template isn't a string and at runtime looks nothing like one (despite how syntactically it looks like one at "compile time"). Given `__iter__()` in Template, it may make more sense/would be more "natural" to Union Template with List or Tuple more than with a single string.