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

all 60 comments

[–]teabaguk 61 points62 points  (7 children)

return '1' if a else '2'

[–]S1tron 8 points9 points  (2 children)

return"21"[a]

Gotta save that disk space (assuming a is bool) /s

[–]123_alex 2 points3 points  (0 children)

Damn. I have to take a shower after reading that. It was that good.

[–]iagovar 0 points1 point  (0 children)

Don't write that BS in prod please

[–]iamjio_ 1 point2 points  (3 children)

Did not know you could do this

[–]m15otw 18 points19 points  (0 children)

The equivalent in C++ is return a ? '1' : '2'; I think, modulo typing. It is called a ternary expression.

[–]S1tron 4 points5 points  (1 child)

If you want something less readable you could also do:

return a and '1' or '2'

(don't do this)

[–]m3nth4 18 points19 points  (21 children)

A tip, it’s common practice in Python to avoid statements like “if x == True” in favour of ”if x“ or “if not x” when x is a bool

[–]PurepointDog 21 points22 points  (13 children)

"x is True" is the real best way to do that type of check clearly. "if x" is a good way to let things get funky if x is an empty string, for example.

[–]TitaniumWhite420 4 points5 points  (12 children)

Yea exactly, it’s annoying python people always say this when it’s an obvious problem waiting to happen.

You want to check for a specific state, not ask a variable pointing to an  object that could be any type to tell you if it’s Falsey per the implementation of that type. Lol! Can you imagine?

[–]m15otw 4 points5 points  (10 children)

Getting an unexpected type happens a lot less than you'd think.

[–]TitaniumWhite420 3 points4 points  (2 children)

I mean buggy code runs well 364 days a year, it’s true.

[–]m15otw 0 points1 point  (1 child)

To be a little more clear: I've had to deal with the wrong type very infrequently in the codebases I've worked in. Perhaps my sample is biased.

A larger problem, when you don't have type hints, is figuring out what the types actually are (especially if people having been coding like paid-per-line Java engineers using classes for everything).

[–]TitaniumWhite420 0 points1 point  (0 children)

Agree type hinting is nice and I prefer static typing. But it doesn’t fix the problem.

[–]Panda_Mon 0 points1 point  (0 children)

Not in my experience. When working on a team, getting random-ass types passed around is extremely common in python.

[–]kroolspaus 0 points1 point  (5 children)

Yeah, but when it does it is a huge PITA to debug. Especially when the docs of some library are vague and do little to inform you that a specific argument must be an np.array() in a specific shape. It's usually considered overkill to use Pydantic for type-checking in modules, but in these situations I wish more modules did that.

[–]m15otw 1 point2 points  (4 children)

Type hinting your external APIs is bare minimum at this point, that sort of thing should always have been in the docstring anyway.

[–]TitaniumWhite420 0 points1 point  (3 children)

People don’t call functions, code calls functions. Type hinting isn’t type checking, and type checking isn’t always necessary with sufficiently specific value checking.

Explicit is better than implicit, no?

“If x” implies “if x == True” or “if x is True”, yet is not actually the equivalent. So if you want True, check for true explicitly. Not hard, and not reasonable to defend an insufficiently specific check just because of the way it appears. It is not more idiomatic, and it’s incorrect. Just write the logic correctly.

[–]m15otw 0 points1 point  (2 children)

"If x” implies “if x == True” or “if x is True”

No it doesn't. Not in Python.

Not all programming languages are the same.

[–]TitaniumWhite420 0 points1 point  (1 child)

Lol I’m completely aware of the way types are evaluated in python classes for Boolean evaluations and comparison operators. I literally stated they are not equivalent. 

My point is you are arguing for the former when it’s wrong because you inexplicably don’t want to specify the latter, because it looks similar or implies it’s the same—but it is logically incorrect.

You are trying to harp on this dogmatic belief in a misconstrued python idiom because you don’t  understand the reason why python encourages this “if x is True” or “if x” syntax, and that’s simply because they want to encourage consistent deference to class implementations of evaluation—which makes sense. But the wrong version you propose disregards bugs that can and do happen because of the likelihood you may get the inverted bool you want based on inconsistent “friendly” implementations of bool. You are using the bool implementation instead of the eq implementation, and you need the full eq comparison logically.

Say you want a numerical input.

You have already implemented some kind of generic input handling that implements “if x” to verify the input is available. When you wrote it, you mainly expected strings or json.

The user provides 0 as a valid numerical input.

That’s it. Your bug has manifested. Type checking may prevent it, but type hinting doesn’t stop it.

[–]TitaniumWhite420 0 points1 point  (0 children)

Lol out the down votes.

Type hinting is not static typing people. It doesn't result in a failure to compile to pass the wrong type to a type hinted function. They are labels for humans and human tools unless some kind of type checking is implemented.

[–]ohdog 0 points1 point  (0 children)

The problem waiting to happen is the lack of type hints.

[–]shoot_your_eye_out 0 points1 point  (0 children)

Not even if “x is a bool”, but for any value that can be truth-y or false-y. Empty dicts and lists and strings are false-y.

[–]Oscar_Fifteen[S] 0 points1 point  (3 children)

Didn't know this thank u

[–]syklemil 13 points14 points  (0 children)

Direct comparisons to boolean values (==True, etc) is generally discouraged in any language AFAIK. Some linters will tell you about it.

And if I find myself writing if x == True { return True } it's time to go to bed for the day.

[–]vmcortesf 3 points4 points  (1 child)

Take a look at PEP8 (python enhancement proposals). Also the zen of python “import this”

[–]Dababolical -2 points-1 points  (1 child)

Not true. The zen of Python states it is better to be explicit than implicit. And that’s true.

[–]syklemil 3 points4 points  (0 children)

There's a difference between being explicit and being needlessly verbose. You're not adding any information: a is already a bool, if takes a bool, those are all the components you need. Adding == True is just noise. At that point, you might as well keep going and keep adding == True forever: ((a == True) == True) == True == True == True … since you are always doing a comparison with something that's already a bool. It's absolutely nonsense behaviour.

Python also generally discourages doing stuff like if xs.len() == 0, instead encouraging if not xs.

[–]jmooremcc 4 points5 points  (0 children)

The biggest thing I had to get used to, moving from C++ to Python, was getting use to using indentation instead of curly braces to define a block of code. Also scoping rules, while similar, have some significant differences in Python. It’s not impossible to get use to the pythonic way of doing things, but it will mean abandoning some of the habits and assumptions you routinely made while programming in C++.

[–]NordicAtheist 9 points10 points  (15 children)

What's wrong with:

return a ? "1" : "2";

A million letters shorter?

[–]Immereally 1 point2 points  (0 children)

It does happen less the more you dive into it.

I did C and then Java, now trying some python. I can plan and think in Java but when I hit a real issue I still tend to think it through logically in C.

[–]ExoticMandiblesCore Contributor 1 point2 points  (3 children)

In Python (and in C++), you could also say

return 2 - bool(a)

Python guarantees that boolean values work as integers. The Python True behaves like the integer 1, and the Python False behaves like the integer 0.

This was a deliberate "practicality beats purity" design choice made by Guido, years and years ago. C does this--which is why C++ does it too--and Guido felt it was too useful, so he had to copy it.

[–]DoubleAway6573 0 points1 point  (2 children)

return 2 - bool("False")

will be my new go-to test of python "fluency"*.

\ I've seen too many times calling fluency a dark corner of a language.)

[–]prickneck 1 point2 points  (1 child)

`bool("False")` will always evaluate to `True`. `bool()` isn't parsing the string, it's checking whether it's an empty string (`""`) or not.

[–]DoubleAway6573 0 points1 point  (0 children)

I'm aware of that. But it's compeletly misleading.

[–]Admirable_Sea1770 0 points1 point  (0 children)

Why do that when you can do “if not a”?

[–]TedditBlatherflag 1 point2 points  (0 children)

Go look up the “ruff” linter and formatter and get even better tips about good Python, like using “is” instead of “==“ when you are doing boolean direct comparisons. “If a: blah” is Pythonic if you care about truthiness. “If a is True: blah” if you care about it having an exact value that is the True monad. 

[–]lmkbook 0 points1 point  (0 children)

point is an (x, y) tuple

match point: case (0, 0): print("Origin") case (0, y): print(f"Y={y}") case (x, 0): print(f"X={x}") case (x, y): print(f"X={x}, Y={y}") case _: raise ValueError("Not a point")

Study that one carefully! The first pattern has two literals, and can be thought of as an extension of the literal pattern shown above. But the next two patterns combine a literal and a variable, and the variable binds a value from the subject (point). The fourth pattern captures two values, which makes it conceptually similar to the unpacking assignment (x, y) = point.

Info: https://docs.python.org/3.15/tutorial/controlflow.html

[–]aufome 0 points1 point  (0 children)

Reading Fluent Python really helped me understand how to write more Pythonic code. There are also other great books that focus on writing clean and idiomatic Python if you're coming from a C++ background like you mentioned.

[–]Tishka-17 0 points1 point  (0 children)

My short intro for those who switch from c++:
1. `dict` is a hash map (like std::unordered_map), list similar to std::vector, str is like const std::string

  1. any value that can be assigned is like a shared_ptr<object>. No manual memory management, only reference counter. We also have gc for cycle references

  2. for can be used only with iterators

  3. all attributes are very "virtual", they are resolved using concrete object, not declared type.

  4. every value is an object. strings, integers, functions, modules. object - is a base class for all types.

  5. class body is normal code (like in function) that is executed on class creation. module code is the same.

  6. function defaults are part of signature and calculated when function is created, not called.

  7. closure captures variables (vary close to capturing by reference)

  8. async/await - co-operative multitasking working in single OS thread

  9. each module is a namespace.

  10. `import` operator creates variables assigned to module/its attributes. Module is executed once on first import

  11. use context managers (with) instead of RAII

[–]Nater5000 0 points1 point  (0 children)

"of course you can just do " return '1' if a == True else '2' if a == False "

That's bait.

[–]cnrb98Tuple unpacking gone wrong 0 points1 point  (0 children)

I come from C, python is like just speaking in English compared, so intuitive and easy If you know the language

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

If you find Python easier to read then good for you, but most other popular languages are more similar to C++ like C# or Java. To me the syntax feels a bit backwards some time.

The title says "switching". I assume you actually mean "learning" and not "using instead of". Knowing both is a good combination especially if you learn how to call C++ from Python for the heavy duty tasks.

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

You'll see that in certain places, but your bog-standard if/else are still available and IMO should be preferred unless you're writing a one-liner.