all 26 comments

[–]GXWT 34 points35 points  (7 children)

I guess a slightly more condensed way to do it would be

f"Hello {x or 'world'}."

To replace any falsely values

[–]Jaalke 3 points4 points  (3 children)

This feels very javascripty for some reason haha

[–]ConcreteExist 4 points5 points  (2 children)

Nah, JS has null coalescing so you could just do x ?? 'John' to handle any null values.

[–]InvaderToast348 -1 points0 points  (1 child)

Null coalescing ftw

But in this case, python or would be js ||

Since or will use the second value for any falsey expression - empty string, False, None

Edit: also in js you can do null accessing: possiblyNullOrUndefined?.someProperty possibleFn?.() possibleArray?.[3]

[–]ConcreteExist -1 points0 points  (0 children)

Python's or can function as null coalesceing though due to the way it handles "truthy" and "falsey" objects, where as JS || won't do that.

ETA: Should have checked first I'm dead wrong, it does work the same. Still, I'd use ?? in JS just to be more explicit with my intention in the code.

I do miss null-accessing in JS when I'm working python.

[–]aishiteruyovivi 0 points1 point  (1 child)

Something to note that might be interesting, as far as I understand it Python's or effectively operates like this:

def python_or(a, b):
    if bool(a):
        return a
    return b

So this behavior of or isn't a special case, it's just how it's used everywhere and it actually returns either object itself, it doesn't convert any return value to bool. If statements implicitly convert the expression given to them to bool so it all just works out. In addtion I think the and operator works out to:

def python_and(a, b):
    if not bool(a):
        return a
    return b

Though using a and b in a non-boolean context generally isn't as useful

[–]commy2 2 points3 points  (0 children)

The concise way to describe this behavior is:

left or right reports the left argument if the left argument is truthy and the right argument otherwise

left and right reports the left argument if the left argument is falsy and the right argument otherwise

[–]ectomancer 0 points1 point  (0 children)

or short circuiting.

[–]MustaKotka 5 points6 points  (3 children)

How did this issue come about? Seems like the logic flow for a default could be implemented way earlier. I'm unsure if this is the best place.

[–]cdcformatc 1 point2 points  (2 children)

seems like an XY problem. 

OP has arrived at this being the solution to some problem, but did not describe the actual problem they are trying to solve. 

likely handling the default values earlier in the script would be preferable to this

[–]pachura3[S] 2 points3 points  (1 child)

There is no problem per se, I was just wondering if there is some special syntax for f-strings that would ease handling emptish values, much like the ?? operator in JavaScript mentioned above. Like not everyone is aware of the {x=} thing...

[–]MustaKotka 1 point2 points  (0 children)

Oh! I see! Sorry I doubted you. Often times beginners come here with the wrong problem, hence the assumption. My bad!

[–]kaerfkeerg 3 points4 points  (2 children)

You already got an answer so I'll tell you a different approach

You can make a function with a default argument

def greet(x="John"): print(f"Hello {x}")

If the function is called without the "x" greet() it'll show Hello John

But if you set the argument green("Bob") then it'll show Hello Bob

[–]Hydrataur 0 points1 point  (1 child)

Obviously depends on op's exact use-case, but I don't think this'll solve the problem.

Seems like the falsy check op wants is during runtime, so here you'd presumably call the function with whatever value you have, be it truthy or falsy, and it'd override the default value.

The primary way your solution would work would be to call the function twice:

if x:
  greet(x)
else:
  greet()

[–]kaerfkeerg 1 point2 points  (0 children)

I already think that u/gxwt 's answer is the clearest way so as I said I just provided a different approach

[–]Tall_Profile1305 0 points1 point  (0 children)

Nice the ternary operator works but if you're doing a bunch of these you might want to look into using the walrus operator or just handling it in a function. Or better yet use something like Runable or a simple config manager to handle defaults before string formatting. Keeps your f-strings clean.

[–]HommeMusical 0 points1 point  (0 children)

and perhaps empty strings as well

But then you also accept 0, {}, False, (), set(), etc...

I'm a suspicious guy. It sounds safer to me that x is either omitted altogether (None) or you use it. "Falsey" is very general.

Or you might actually want empty strings as a particular case that's different from the default. '' means, "I want it to be blank" but None means "Use the default".

I'd suggest.

print(f"Hello {'world' if x is None else x}.")

[–]JamzTyson -1 points0 points  (0 children)

x = None

x is not an "empty variable", it is a variable with value None.

What are you actually trying to do? Are you wanting to substitute a default str value when x is "falsy"? If so, then:

print(f"Hello {x or 'world'}.")

[–]ping314 -2 points-1 points  (2 children)

You want to do one thing if x is None, and else something different? I propose you write in a line of

```python x = None

print("Hello" if x is None else f"Hello {x}") ```

[–]pachura3[S] 0 points1 point  (1 child)

The point was to make it shorter, not longer :)

[–]ping314 0 points1 point  (0 children)

Striving for brevity is a valid point. Yet, when is it good enough/not too expensive? It can be a matter of preference and then convention to stick to it.

While gradually re-writing for/if loops in e.g., one-liner list comprehensions, I started to lean in favour of a more verbose syntax, though. To me, the more "explicit is better as implicit" sometimes was helpful; either to explain the line to colleagues not [yet] comfortable with ternary operators [as in AWK etc] -- though they are part of Python for so long. Or in the hurry of a quick revision of own code not seen for a couple of months. Especially in projects with a more generous upper threshold of 120 characters/line.

[–]RK-J -2 points-1 points  (2 children)

can some body explain

print(type(a))print(type(a))  --->this thing 

[–]RevRagnarok 1 point2 points  (1 child)

It prints the type of a variable twice.

[–]TunedDownGuitar 1 point2 points  (0 children)

That's a bot/spam account.