Python's ternary operator
Ғылым және технология
It's not so hidden!
Yes, like nearly every modern programming language Python also has a ternary operator, although it doesn't refer to it as such. While other languages typically use "?", Python chose to use "if".
― mCoding with James Murphy (mcoding.io)
Source code: github.com/mCodingLLC/VideosS...
Conditional expressions docs: docs.python.org/3/reference/e...
PEP introducing conditional expressions: peps.python.org/pep-0308/
How Python determines if x is truthy: • x to bool conversion i...
Default mutable arguments: • The Best Way to Check ...
SUPPORT ME ⭐
---------------------------------------------------
Sign up on Patreon to get your donor role and early access to videos!
/ mcoding
Feeling generous but don't have a Patreon? Donate via PayPal! (No sign up needed.)
www.paypal.com/donate/?hosted...
Want to donate crypto? Check out the rest of my supported donations on my website!
mcoding.io/donate
Top patrons and donors: Jameson, Laura M, Dragos C, Vahnekie, Neel R, Matt R, Johan A, Casey G, Mark M, Mutual Information
BE ACTIVE IN MY COMMUNITY 😄
---------------------------------------------------
Discord: / discord
Github: github.com/mCodingLLC/
Reddit: / mcoding
Facebook: / james.mcoding
Пікірлер: 165
The "ter" comes from Latin, where "ter" means "three times" and "tres" just means "three", "ternus" is treefold and so on. So ternary ("ternarius") is three-ish, having the quality of three, being composed of partes tres (three parts). The root of "tri" lies in ancient Greek. So it's just a matter of which fancy dead language you find cooler to flex your smarts, when naming things.
@sanscipher9166
Жыл бұрын
Numeric systems notably went with latin numbers.
@amritlohia8240
Жыл бұрын
@@Agesilas2 In English we tend to add a letter after the number for this, so e.g. house numbers can go 7, 7A, 7B, etc. You also see this in legislation, where an amendment might insert "section 7A" in the same way as you might have "section 7 bis".
@RagHelen
Жыл бұрын
No, it has nothing to do with Greek. Latin -ri- becomes -er- in open syllables between t and s: tris > ters > ter (thrice). Accordingly the adjective: tersno- > terni, as in ternae litterae (three letters each). A similar pair can be found in English 'dec-er-n' (from Latin, hence -er-) and 'c-ri-tic' (from Greek, hence -ri-), both words from the same root.
@4cps777
Жыл бұрын
"being composed of partes tres" gallia est omnis divisa in partes tres
@teoconserv9954
Жыл бұрын
@@4cps777 quarum unam inclunt belgae. Glad someone got the reference 😁
What's funny is that the python community held a vote for the ternary operator syntax. They came to a consensus on what syntax to use, then Guido came in and used his own.
@mme725
Жыл бұрын
What was the difference?
@indigojones4442
Жыл бұрын
@@mme725 the top voted syntax was (if cond: x else: y) Guido vetoed it and we now have x if cond else y Which was voted 4th
@kyle-silver
Жыл бұрын
“Flames, pleas to reconsider, etc., to /dev/null” What a savage 😂
@saadisave
Жыл бұрын
@@indigojones4442 Guido's syntax is consistent with the list comprehension syntax
@brianb.6356
Жыл бұрын
@@indigojones4442 Guido was right then, adding colons to a one-liner is terribad.
It's worth noting that there is merit to calling ?: in any form a "conditional expression." 'Ternary operators' are operators which accept 3 arguments, no matter what they do. For example, I could define a mathematical ternary operator [a $ b $ c ↦a * c - b]. The only reason programmers know what "the" ternary operator does is because afaik there is only one such operator (up to operator symbol and argument order) that is ever defined in any practical language, that being [a ? b : c].
@guiorgy
Жыл бұрын
Makes sense
@kcwidman
Жыл бұрын
Valuable clarification here!
@0LoneTech
Жыл бұрын
We're looking at Python here. 3>x>1 is a valid expression distinct from (3>x)>1 or 3>(x>1); it is more akin to (3>x and x>1). You can chain more comparisons, but this one is ternary. See the Python Language Reference section 6.10, Comparisons. Side note: ?: *is* called the conditional operator in C.
It didn't take me too long to learn to check date stamps on stack overflow for this very reason.
I literally had the same idea of flagging SO posts as outdated sometime ago, it would solve so many issues with outdated answers!
@brucewayne1777
Жыл бұрын
This comment has been closed as a duplicate of 2:40
"Ternary (from Latin ternarius) or trinary is an adjective meaning 'composed of three items'." From Wikipedia
@tsalVlog
Жыл бұрын
Exactly this. The English definition for laypersons (not in the context of Maths) is "composed of three parts". In Maths it's "using three as a base".
How to learn Python? Many tutorials I don`t know where to get started
@MeiLinFjellstad-oe2cc
Жыл бұрын
I learned with the books "Programming not Painfully Boring", "Smarter Way to Learn Python" and "Head First Python". I like their method of learn by doing. After learning the fundamentals, any other concept becomes much easier.
@0LoneTech
Жыл бұрын
Have you considered the Python Tutorial, labeled "start here" in the documentation?
Stale info is turning into a huge annoyance on the internet. Now when searching stack overflow you often times have to pay attention to the dates just to make sure the answers aren't over a decade old! Sometimes that's fine, with python that's usually a huge problem.
@georgeprout42
Жыл бұрын
Some of the stuff I've been looking for (very narrow field specialist thing) just resulted in finding someone asking "my question" 20 years ago. And a 20 year old answer didn't solve it, but nudged me enough to crack it. I created an account just to post the solution. Hopefully it'll be useful to someone in the next decade or two. So yes but no. Preserving the old answers and flagging them as historic is fine, but never remove them.
@georgplaz
Жыл бұрын
I hate it when my coworker argues their absurd position with some decade old python 2 answer 😞
@LordDoucheBags
Жыл бұрын
Very true in machine learning problems. There are still answers from 2010 claiming that a single layer in a neural network is sufficient
@bakedbeings
Жыл бұрын
It'd might have the added benefit of discouraging the sometimes lazy/obnoxious "that question has already been answered" replies.
@anon_y_mousse
Жыл бұрын
@@bakedbeings I hate when questions are labelled duplicates when they clearly are not.
It's called ternary because it comes from Latin. "bīnus" is twofold, "ternus" is threefold, "quaternārius" is fourfold and so on
@spitsmuis4772
Жыл бұрын
Or more simply: bis is twice, ter is thrice
@jacobstern2150
Жыл бұрын
None of these answers actually explain why ternary is used here instead of trinary
@sanscipher9166
Жыл бұрын
@@jacobstern2150 Tri- is a Greek root. Ter- is a Latin root. Numeric system use Latin roots.
@RagHelen
Жыл бұрын
@@sanscipher9166 No, that's wrong, no Greek involved.
@sanscipher9166
Жыл бұрын
@@RagHelen Wrong how? Elaborate.
2:35 The one good place for these is golf code, where ``[a,b][cond]`` is the shortest way to evaluate conditionals in python. If you don't want b to be evaluated when not returned (maybe for recursion), you can use ``a * cond or b``. If a also can't be evaluated, you use ``cond and a or b``, which still saves 2 characters over the if-else syntax. That said, golf code != good code, don't put this in your projects!
@NicolasChanCSY
Жыл бұрын
I believe Branchless programming is not a good optimisation strategy in Python, which is not known to be the fastest programming language. There are many things that can be optimised before resorting to branchless programming. I have not timed it, but I suspect creating a new list containing the two evaluated `a` and `b` and then indexing it, probably would not be significantly faster than conditional expressions.
@12-343
Жыл бұрын
@@NicolasChanCSY Code golf is not the practice of optimizing time or space complexity in the usual sense, but rather the problem of "write this program using as few characters of code as possible". These are generally simple problems like fizzbuzz, where optimization isn't really a concern. That method is undoubtedly slower, but it is shorter (in literal length) than a normal conditional and therefore has its use case in code golf problems.
@erikkonstas
Жыл бұрын
"cond and a or b" will fail if "not a" is True.
@12-343
Жыл бұрын
@@erikkonstas Yeah, generally there will be some sort of workaround for it though (even just swapping the a and b values sometimes)
@NicolasChanCSY
Жыл бұрын
@@12-343 I see. I misunderstood it. Thanks for pointing it out for me. Nevertheless, the risk of logical bug outweighs the pleasure of shorter code in your examples in my humble opinion. 😀
Lol sometimes the appropriate edit for a very old SO post.. is to delete it. I don't think people have the heart for that
@mCoding
Жыл бұрын
With 900 upvotes I could see why they wouldn't want to!
@teoconserv9954
Жыл бұрын
@@mCoding Also sometimes very old info is useful in itself. I had that be the case a couple of time and was thankful it was still there.
@lawrencedoliveiro9104
Жыл бұрын
That index-into-a-tuple idea is quite good. It also generalizes to a dictionary, giving you multiway labelled switch expressions.
Great video! An important discussion is when to use conditional expressions (ternary operators) in Python? There is a tradeoff between efficiency vs. readability. For short expressions, the conditional expression is certainly a great tool. But if the expressions are long, I prefer to write out the if-else on separate lines as this improves the readability. I also never use the conditional expressions in my own videos as not everyone is aware of them, to avoid alianating people.
Valid criticism of stackoverflow at the end. I wish you'd explained exactly why those answers are wrong.
@joostvisser8537
Жыл бұрын
They are not wrong per se, the code is still valid Python. _return (a, b)[cond]_ will return _a_ if _cond_ evaluates to _False_ , and _b_ if _cond_ evaluates to _True_ . The reason it is 'wrong' is that this syntax is not really used for this purpose anymore so it will be incredibly confusing for those reading your code. _return a if cond else b_ is simply much more intuitive and also convention.
@KHariram
Жыл бұрын
In [x, y][cond == True], both x and y are always evaluated. In the other one, cond and x or y, the post itself talks about its drawback that x needs to be truthy.
@cool_scatter
Жыл бұрын
He basically did explain it… they were written before the conditional expression existed, but now it does so just use that.
Thank you for another great video! And please tune up your volume a bit, you sound way quieter than most youtubers.
Seeing your facial expressions while discussing the oddities of Python is very satisfying hehe
short simple and concise. Loved it!
Great examples of use cases where conditional expressions can be used. E.g. for setting a default immutable value.
The third answer on StackOverflow mentiones that the answer is for Python versions before 2.5 so it's ok
@erikkonstas
Жыл бұрын
Note that it was never correct, though.
I really don't like Python's ternary. For anything non-trivial, the flipped order makes it confusing to read. I mostly use it only on list comprehensions or when the condition or expressions are trivial; otherwise, I prefer an if/else block.
@erikkonstas
Жыл бұрын
If by "list comprehensions" you mean "[f(x) for x in a if g(x)]", then what you're seeing is not the conditional operator.
Oh, I'd been using the wrong ones for a while now. Didn't know there was an official version now! 😅
@erikkonstas
Жыл бұрын
"Now"...? I question whether you should ever work as a software developer... or really any office job where there are meetings and seminars...
“Ter” is the prefix used in *ordinal* numbers. Same as we say _third,_ not _threed._ So… one, two, three vs. primary, secondary, tertiary. Somebody must have conceptualized the operation as ordinal (e.g., taking a third value) rather than cardinal (e.g., taking 3 values).
"Deprecated" might do the job of "Severely Out Of Date" without negative impact on reputation.
Good advice for stack of. 👍👍
i gotta try that last one
The problem with c and x or y is that when x evaluates falsey it still results in y even though that's incorrect behavior compared to x if c else y
I would have preferred the C-style syntax of: x = if ( cond ) a else b; # as in making it ternary by explicitly using parens, but that's probably just me. Of course, I still haven't settled on a clean syntax in that regard for my own language. Far too many years have passed for me to be undecided.
@AssemblyWizard
Жыл бұрын
That's how Rust & Kotlin do it, but C doesn't support such syntax because ifs are statements and not expressions
@mCoding
Жыл бұрын
Yes sometimes I wish this too but alas the vote was decided long ago and it's better we just accept it and save ourselves the internal turmoil.
@erikkonstas
Жыл бұрын
@@AssemblyWizard No no, there is a point here; if "a" is an expression then one can tell it from a statement; it will neither be enclosed in {} nor end in a ; before the else. Of course, it's debatable whether we trust the naked eye enough to make out at a glance that a single semicolon is missing.
Re Stack Overflow: Fix your sort. It's set to "Highest Score" instead of "Trending". This should generally be good enough.
Me and My homie : "Stuff the codes into 1 line and sent it to the teacher."
Standard stackoverflow. Systemic problem with no solution that is at least partially caused by overeager mods.
Conditional operator is different from ternary, because you can't use it as a reference. (my_score if winner == "me" else opponent_score) += 1 won't work in python. (winner == "me" ? my_score : opponent_score)++ Works in C++.
@mCoding
Жыл бұрын
This has more to do with C++ having references than there being a difference between conditional versus ternary operator. Python does not have reference types and therefore does not support reference assignment, using ternary operator or otherwise.
@erikkonstas
Жыл бұрын
Assignments are not expressions in Python.
@0LoneTech
Жыл бұрын
@@erikkonstas Recently there does exist an assignment operator := (as in Pascal) known as the walrus operator. Side note, Python always uses references, more explicitly in the case of weakref. It doesn't provide a way to replace an object, something central to Rust's borrow checking, nor a way to refer to an in-namespace slot (although properties are quite close). "Doesn't have references" is thus another C++ centric view; just like there are other ternary operators (e.g. a
@erikkonstas
Жыл бұрын
@@0LoneTech := has been made too restricted on purpose though, and lacks the flexibility of normal assignments (that is, you can't unpack). And yeah I don't think Python inherently has any notion of references in its syntax like C++ does (that is, if we define "reference" to be "insert * for me here", since Python doesn't have pointers to begin with; of course one can argue that mutable objects are references to themselves).
Can't argue with option Q.
using a tuple method still useful in code golf :)
@erikkonstas
Жыл бұрын
And code golf still bad for prod code.
Middle English, from Latin ternarius, from terni three each; akin to Latin tres three
cool
So, multiple if statements at the same time?
@Alche_mist
Жыл бұрын
Please, don't nest ternary (conditional) operators in any language where you can help that. It's almost universally reviled due to it being unreadable. In Python, it would look something like: `a if cond1 else b if cond2 else c` Multiple nested IFs in Excel (where it's often unavoidable) is the bane of its users and an important reason why you shouldn't use Excel for too complex of a work.
@SkyFly19853
Жыл бұрын
@@Alche_mist I see.
the one-liner
The walrus operator is next I guess.
That's just one of the ternary operators. A[b:c] is another. The adjective 'ternary' was borrowed from mathematics. 'Trinary' seems to be used only by astronomers.
ternary from tertiary (primary, secondary, tertiary)
I always wondered why bools are also integers. (False+3)*(4-True) returns 9 And isinstance(True, int) returns True
@delta3244
Жыл бұрын
There's a ton of tradition. Abbreviated explanation: 1/0 = true/false starts in mathematics, became true of machine code, so was also true in the first languages, so became true by convention as new languages were developed.
@erikkonstas
Жыл бұрын
Yes, because issubclass(bool, int); there are some languages like Java and C# which don't allow this tho (and don't have a notion of "truthiness", so where a bool is expected only a bool can be placed, which an int is not)
Ahhh this was a short
1:04 Lol, imagine if they chose N instead.
0:15 Python is too cool for using question mark in its ternary operator because its aim is to create code that reads like english, not some symbol soup like Perl.
the other answers are useful when golfing
@mCoding
Жыл бұрын
Excellent point I didn't consider, but perhaps such answers would be better suited on the codegolf stack exchange rather than stackoverflow as the goals of these two sites are very different and usually at odds with eachother.
Python ternary can be more complex, such as : z = 'positive' if x > 0 else 'negative' if x < 0 else 'zero'
@mCoding
Жыл бұрын
Can be, yes! But keep in mind that chaining these together quickly becomes difficult to read and using a normal if elif else may be better suited.
Unlike c++ you can't "assign" ternary expression to something while you can "assign" something to it In other words you can't do this x=y=0 (x if True else y) = 1
@catlooks
Жыл бұрын
(c ? a : b) = r; is a perfectly valid c/c++ snippet tho
@Cyberguy42
Жыл бұрын
@@catlooks Yes, I think the OP was trying to say that you can do that in c but not in python
@mCoding
Жыл бұрын
This is because C++ has references and supports reference assignment. Python does not have references and therefore does not support reference assignment. This doesn't really have anything to do with the ternary operator. E.g. `int x = 0; int& y = x; y = 1;` works in C++ but will not work in Python, it would reassign y instead of changing x.
@frobeniusfg
Жыл бұрын
@@mCoding Ok, let's make it full pedantic. Python system of value semantics makes conditional expression have fewer semantic capabilities compared to the ternary operator in C++.
@erikkonstas
Жыл бұрын
@@frobeniusfg If you are here just to troll, go back to your kindergarten please...
It might be unusal style but what is wrong with (FalseStatement, TrueStatement)[test]? Granded it will excute both statements so be aware of that, otherwise it is fine. Also which purpose did they serve back then, that they don't do now? Just tested, the trick still works with Python 3.11.
@indigojones4442
Жыл бұрын
Tuple indexing style has to evaluate the value of both TrueStatement and FalseStatement, conditional expressions can use short circuiting. Tuple indexing also can't handle falsy values, e.g. X = 0 if [] else 1 works, but x = (0, 1)[[]] doesn't.
@georgplaz
Жыл бұрын
it is not readable. also, it violates the python paradigm that there should ideally be exactly one way to solve a problem. there is a built-in operator for exactly this situation, so you should use it
@erikkonstas
Жыл бұрын
@@georgplaz No, look at Indigo's reply above.
@georgplaz
Жыл бұрын
@@erikkonstas how does their reply invalidate mine?
@erikkonstas
Жыл бұрын
@@georgplaz Because there are more important reasons than unreadability and violaation of the Zen of Python (which BTW is not aimed at Python users but at Python developers).
Why "bonkers"? This was probably borrowed from Lua and it actually works in Python. Not to say, that it's more elegant :)
I have zero problem with the wordiness of "if else" instead of "? :", but the order would throw me. It looks almost as bad as an "unless" statement in Perl. Which is so bad a construct that Mark Rendle featured it as the only means of conditional testing in his hypothetical "The Worst Programming Language Ever" stump speech. It wouldn't be so clumsy if it followed the same order as if...else statements, but alas, it doesn't even do that. On the plus side, anything that allows an expression instead of a statement is progress.
@mCoding
Жыл бұрын
What a throwback to hear about "unless" on perl :)
My fave is: a = None b = 2 var = a or 2
@wholebrain8457
Жыл бұрын
Can't that be reduced to ` var = x ` ?
I’m not a fan of this shortcut, my brain likes to see the extra 3 lines 😅
@Alche_mist
Жыл бұрын
You brain or your code-illiterate manager using the infamous "lines of code" metric?
@mCoding
Жыл бұрын
Nothing wrong with this approach at all
Surely it should be called a binary operator? It returns (and only returns) one of two possible options.
@mCoding
Жыл бұрын
Great question! The binary/ternary refers to the number of inputs, not the number of possible outcomes. In this case the two return values and the condition are considered to be the three inputs.
@tbird81
Жыл бұрын
@@mCoding It seems completely arbitrary, which I guess everything ultimately is, but also inconsistent. What else do you count total numbers of inputs and outputs and name it after that? There's other things with a total of three that aren't called ternary. If I'd never heard it before I'd assume it was some sort of low level architecture that could handle -5V, 0V, or +5V for instance (as opposed to binary). I think the best name for it would be "inline conditional", or a "conditional operator".
@0LoneTech
Жыл бұрын
C's ?: is a 2:1 multiplexer (often shortened mux): One control input, two value inputs, one result. Naming it "ternary operator" is a bad habit, made under the assumption there could be no other ternary operator; it is actually called the conditional operator. Python also already has a set of n-ary operators in the comparison syntax, and 2-4 arguments in the slice syntax. Lisp/Scheme make most operators n-ary (turning them into reductions).
Isn’t it “tertiary”?
@restcure
Жыл бұрын
kzread.info/dash/bejne/d3ttxpSbgaWzmM4.html
Thats not a ternary operator. I can say that not as a programmer but as a mathematician. For one thing its not ternary, and for a second thing is not an operator. Its unary. There is a single input argument: the condition. Based on that argument (True or False) you get the output of the operator. A single input with two possible values get mapped in a one-to-one correspondence to one output with two different possible values. Contrast the number of inputs with that of a binary operator, say, an addition operation, which clearly requires two inputs. The function youre talking about does not have three inputs. It doesnt even have two. It (the IF function) gives one output for its one input (a boolean), and you assign the possible outputs to it, as you would with any function, binary, unary, or otherwise. A ternary function would take three arguments as input and provide you with a fourth value, an output Its not even an operator. Its a function. An operator gives as output an entity (or class, if you will) of like-type as each of its argument inputs, all of which are also of like-type. Such as the addition of integers, for example. The IF statement takes a boolean as an input argument and returns any class of statement you want it to. As an amateur philologist and etymologist I can comment on the prefix as well. It does also tie into my mathematics expertise, too. The difference between ter and tri is the difference between Latin origins and Greek origins. Generally the grammatical rule is to use the same language for prefixes and for suffixes as you used for the root word. Thats why we can say either quadrilateral (more common) or tetragon for a four-sided shape. One would not say tetralateral or quadrigon. One takes the Greek root and the other the Latin root. Technically one counts the number of sides and the other counts the number of angles. Indeed, the proper pluralization of octopus is octopodes, not octopi. Octopus is a Greek word and pseudointellectuals in English used the Latin pluralization to come up with octopi.
@mCoding
Жыл бұрын
An if expression takes 3 inputs (a, condition, b) and returns one output (either a or b), this makes it a ternary function/operator. There is no difference between an "operator" and a "function" in math. An operator is just a function that you have decided to call an operator.
@leesweets4110
Жыл бұрын
@@mCoding No, my friend, you are mistaken. Speaking as a mathematician, there is a difference, and the IF would be considered a unary function, not a ternary operator. Your "other two inputs", from the mathematical perspective, is just input-output assignment. Youve defined your function, your mapping. Thats all. The function still just takes the one input. The other two supposed arguments just define the underlying function map. I make no comment on how or why the programming community has twisted the terms. Im only speaking from a mathematicians perspective.
@notead
Жыл бұрын
@@leesweets4110 You're arguing against 60 years of computer science. Even if you were to be semantically correct (which you are not), it is a term that has been used for decades to refer to this form of syntax.
@leesweets4110
Жыл бұрын
@@notead I absolutely AM correct about the mathematical meanings of those words. I have also repeatedly emphasized the fact that Im speaking from a mathematicians perspective, and know full well computer geeks have perverted words they dont fully comprehend. Im really not sure what you think youre contributing to the conversation. @mCoding OP asked what the difference was between ter and tri. Clearly he has concerned himself with the proper meanings of words and their mathematical connection. I dont see how you can ask such a question and also imply you dont care about the proper meanings of words. I have provided such clarity. Not just for ter and tri, but also operator and ternary.
@anon_y_mousse
Жыл бұрын
@@leesweets4110 What you're talking about is math, this on the other hand, is computer science. Different disciplines use different terms, and I know you know that. You can consider it wrong if you want, but it's just another discipline. In this case I would say it operates on three values, the condition, the true result and the false result. And `if` isn't a function, and in any other context wouldn't even be considered an operator, but this is computer science and we're weird.
I personally find the Python construct to be a complete abortion. Here is what I prefer to use: («if-false-val», «if-true-val»)[«bool-val»] or if you want lazy evaluation: (lambda : «if-false-val», lambda : «if-true-val»)[«bool-val»]() The nice thing is, this generalizes nicely to a multiway switch-expression, which C and its derivatives don’t have.
@anon_y_mousse
Жыл бұрын
I'm not entirely sure what you mean. How would that differ from a regular ternary operator?
@Labicraft
Жыл бұрын
While the true and false condition not being next to each other may be a bit confusing, using tuples, using indexing, using boolean cast to integer and even potentially lambdas and function calls for stuff they were not designed to be used is even worse (plus this will fail if the condition is not purely boolean i.e. when checking if a list is empty you'll have to go bool(list_) or something)
1:17 Yet another reason why it’s a stupid design.