2

I have a one liner if statement that looks like this:

var = var if var < 1. else 1.

The first part var = var looks a bit ugly and I'd bet there's a more pythonic way to say this.

Gabriel
  • 40,504
  • 73
  • 230
  • 404

5 Answers5

18

The following is 39% shorter and in my opinion is simpler and more pythonic than other answers. But we should note that sometimes people get it wrong thinking that 1 is a lower bound being confused by min function when actually 1 is an upper bound for var.

var = min(var, 1.0)
sasha.sochka
  • 14,395
  • 10
  • 44
  • 68
  • 4
    Despite your doubts, I think your answer *is* better and more simple than the asker's original code. Sure, neither is exactly complicated, but this is marginally easier for my brain to parse than the ternary expression is - I'd certainly rather see this one in the middle of some dense, difficult code than the original. – Mark Amery Aug 08 '13 at 22:11
  • 4
    I think it is quite pythonic - it clearly states intent without having to look through extra logic. – tdelaney Aug 08 '13 at 22:12
  • 2
    The OP is comparing to `1.`, not `1`. This can potentially make a difference depending on the type of `var`. – arshajii Aug 08 '13 at 22:17
  • 2
    +1, except that most readers will involuntary tend to associate the word `min` with a lower bound for `var`, when the real meaning is just the opposite. Seen this too many times. For readability, I prefer an if-based version even if slightly longer, and I wish language designers had promoted alternative names for `min` and `max`. Again, there is no need to make things potentially confusing if there is little or no gain. – Mario Rossi Aug 08 '13 at 22:46
  • @MarioRossi, agree with you, that's why I added a small disclaimer. As my final decision I would say this is arguably more pythonic than other answers but harder to understand sometimes. Anyway, this is my personal choice and I would use it myself. – sasha.sochka Aug 09 '13 at 11:08
  • 1
    @sasha.sochka Yes, a lot about personal preference here. This's why my +1 from the beginning (I couldn't find an option "+0.9999999999" :) ). – Mario Rossi Aug 10 '13 at 00:16
9
if var >= 1.:
    var = 1

or if you like one liners

if var >= 1.: var = 1
Brionius
  • 13,858
  • 3
  • 38
  • 49
  • This is the best approach in my opinion, +1. – arshajii Aug 08 '13 at 22:19
  • +1 It's also more readable by the occassional person more used to another programming language. I know, he/she will most probably get lost at other points of the program, but why contribute to confusion when there is no gain but "pythonicity"? – Mario Rossi Aug 08 '13 at 22:28
5

Doesn't eliminate the var = var but it's shorter and one could argue, more pythonic:

var = min(var, 1.0)
Óscar López
  • 232,561
  • 37
  • 312
  • 386
4

Maybe this way would be shorter

var = min(var, 1.0)
Karadur
  • 1,226
  • 9
  • 16
2

You can use the equivalence of True=1 and False=0 to index into a 2-tuple of the possible values:

var = (1,var)[var < 1.]

If var < 1., then this evalutes to True, which is equivalent to 1. This simplifies to:

var = (1,var)[1]

Or

var = var

if not var < 1., this evaluates to False, which is equivalent to 0, giving:

var = (1,var)[0]

or

var = 1

So this one-liner:

var = (1,var)[var < 1.]

is equivalent to:

if var < 1.:
    var = var
else:
    var = 1
PaulMcG
  • 62,419
  • 16
  • 94
  • 130
  • O.O I'm not sure I even understand this line. – Gabriel Aug 08 '13 at 23:58
  • 1
    Interesting construction, but I don't consider relying on `False = 0, True = 1` very pythonic... – Tobias Kienzler Aug 09 '13 at 12:37
  • +1 For originality and applicability in other cases. Personally, I wouldn't use it because of the reasons exposed by @Gabriel. – Mario Rossi Aug 10 '13 at 00:19
  • @Tobias Keinzler IMHO, the relationship is completely pythonic (in the same way as it is an integral part of C). Otherwise, the original language design would have included a separate Boolean type explicitly. – Mario Rossi Aug 10 '13 at 00:48
  • @MarioRossi It is done like it is done, and yet `None` is also interpreted as `False`, so what if at some point `False = None`. And `True = not False` could also be `2`. I'm just saying that the association of Booleans and integers is arbitrary and _not_ pythonic at all but rather backwards-compatibility with C – Tobias Kienzler Aug 10 '13 at 06:29
  • 1
    @Tobias Keinzler Right, especially when `None` is equivalent to C's `null` and C's `null` also evaluates to `False`. I'm new to Python and realizing that "Pythonic" doesn't mean "supported by the Python language" but "preferred by the Python community/language spirit". In that case, I'm extremely glad these Boolean equivalencies / implicit conversions / definition of Python's boolean operators (I don't know how to exactly say it) are not considered "Pythonic". – Mario Rossi Aug 10 '13 at 09:37
  • @MarioRossi - not original at all, this is just "old school" Python from before there was a ternary expression, used as a safer alternative to `condition and true_value or false_value`, see my comments on tdelaney's answer. And also this version *is* guaranteed by the Python language spec, which defines True and False to be equivalent to 1 and 0. But it is inferior to today's ternary expression in that `true_var if condition else false_var` will short-circuit, which is very helpful when `false_var` is implemented using an expensive function, such as a database retrieval. – PaulMcG Aug 10 '13 at 23:52