What does "if var" mean in python?

25,007

Solution 1

in python, writing

if var:

has the same effect as writing

if bool(var):

(where bool is the built-in bool type which also acts as a constructor function for bool objects).

If the value is already a bool (valued True or False) the meaning is clear -- bool(var) returns the same value. For other types, there's almost always a conversion to bool avaliable which depends on the type. For integers (as in C) it's the same as var!=0; for lists or dicts or strings, it's the same as len(var)!=0, and so forth. You can find this in the python docs.

When you define your own class you can define a method via def __nonzero__(self): , which will be called in this context (when your object is passed to bool explicitly, or implicitly in an if -- or while for that matter).

A notable exception: numpy array objects do not convert to bool (they raise an exception). They need to be explicitly converted using constructs like (arr!=0).any() or (arr>0).all()

On similar lines: Don't get into the habit of writing any of

if x == True:     # This only works as expected when x is a bool, or 0, or 1
if x is True:     # Can be useful but you need to understand what it really means.
if x == None:     # Often works as expected, except when it doesn't

Comparison to None should always be done with

if x is None: (or) if x is not None:

There is only one None object, and x is None will tell you if x refers to that object, and will always give you a bool (True if so, False for any other object). Comparing x==None (a mistake I frequently made when starting to use Python) will usually work, but it activates the generic comparison machinery of Python, which is not what you probably want; if x is an instance of a class, the comparison could raise an exception. is is simple and quick and just does that identity test - it can't be overloaded.

Likewise if x is True means "if x is the boolean object meaning true, and no other object at all" -- which can be useful, but is too narrow for the case when you are just testing truth value. Somebody might end up passing 1, which will fail an 'is True' test, but otherwise acts very much like True.

Solution 2

Behaviour differs a little bit from language to language.

Behaviour 1: The variable is converted into a boolean. I.e. there are language specific conversions from different types into a boolean. For numeric values, 0 is usually converted into false while any other value is converted to true. As far as I know, this is the way Python does it.

Behaviour 2: Booleans are numeric values. As above, 0 is usually the only value that evaluates to false

Behaviour 3: Any non-null reference evaluates to true, null references evaluate to false.

This should more or less cover it, but there may be other variations or combinations as well, for instance using fallback to method 2 or 3 if 1 is not available. The point is that it's very much a language specific question.

Solution 3

There are lots of answers already that speak in the general term of "What if does in programming," so let me boil your code out for you.

def valid_day(day):
    if day and day.isdigit():#if day

if signifies the beginning of the if block, and works as the other answers have pointed out. What follows is the boolean expression day and day.isdigit(). and is a Boolean operator that requires both operands (both sides of the equation, in layman's terms) to be True in order to evaluate as True. In this case, both day and day.isdigit() must evaluate to True for the if block to run.

In Python, we think of things as "Truthy" and "Falsey." It's easier to define "Truthy" in terms of "Falsey," because the latter is a much shorter list:

  • None
  • 0
  • False
  • [] "" {} () and the like

Everything else is "Truthy." If you type while -1: print("This loops forever") it will, in fact, loop forever. All non-zero numbers, all non-empty containers (strings, lists, dicts, sets, tuples, etc), anything not explicitly set to False or None will evaluate to True. In this case, the code is checking to make sure that day isn't None, because if it is then day.isdigit() will throw an AttributeError and break the code. You can try it yourself: type None.isdigit() in IDLE. Note that this is likely not the most foolproof implementation, since doing valid_day(31) will also throw AttributeError. valid_day requires a String, even though it's checking numbers.

        day = int(day)
        if day > 0 and day <= 31:
            return day

This is actually repetitive code, since doing int(day) confirms day.isdigit(). If this is your code, perhaps consider a try: except block instead, such as:

def valid_day(day):
    try: int(day)
    except ValueError as e:
        return False #this means whatever you passed to it can't be converted
                     #into an integer: maybe a floating point string?
    if day in range(1,32): return True
    else: return False

This will let you avoid the trap of checking for everything you know might fail. Instead, check to make sure your checks will be able to run, and let your program handle whatever you pass to it. This will also allow you to design a Day class that contains more information than an integer but will still return its calendar day using self.__int__(): return self.calendarday and valid_day(Day()) will return True. In addition, your current code returns None when you should be returning False -- as I mentioned above, None is Falsey, so in most cases this will work (e.g. if not valid_day: do_something_drastic()) but in some cases you may want to deal with a boolean directly.

Okay, there's a mouthful of words for you.

TL;DR: if starts the if block, day and day.isdigit() is true only when day is a non-empty string that contains an integer, and the rest does what it says it does.

Solution 4

The value of the variable is converted to a boolean, i.e. type coercion is performed. How this exactly happens depends on the language. In Python for example, an empty list evaluates to false. In most languages, 0 evaluates to false and any other number to true.

Then of course the variable might already contain a boolean value, e.g.

inBounds = day > 0 and day <= 31
if inBounds:
    #...

Solution 5

if day: is a short way of writing if day == True:. When it evaluates the result of True == day, if day is a simple and basic object such as integer, then the Python interpreter will try to call the built-in value comparison. If day is a class, the interpreter will call its __nonzero__ member function.

For example

class MyClass:
    def __nonzero__(self):
        return False

if __name__ == "__main__":
    c = MyClass()
    if c:
        print "yes"
    else:
        print "No"
Share:
25,007

Related videos on Youtube

Alcides
Author by

Alcides

I'm interested in web development

Updated on July 05, 2022

Comments

  • Alcides
    Alcides almost 2 years

    This is a function in python to validate a day entry.

    def valid_day(day):
        if day and day.isdigit():#if day
            day = int(day)
            if day > 0 and day <= 31:
                return day
    

    I want to know what the expression if day means (in terms of semantics).

    I only know the effect of if on boolean expressions not on variables like integers or arrays.

    • greggo
      greggo over 10 years
      FWIW, the function you give could be documented as: "'day' is expected to be None, or a possibly-empty string of digits; the result will be integer in range 1..31 (if conversion to such can be done) or None in other cases".
    • Matthias
      Matthias over 10 years
      One small addition. The last condition could be written as if 0 < day <= 31.
    • greggo
      greggo over 10 years
      While we are picking those nits - I'd write it as 1 <= day <= 31.
  • Maxime Lorant
    Maxime Lorant over 10 years
    Nope. 0 is evaluates to false and any other numbers to true in reality.
  • dstromberg
    dstromberg over 10 years
    This is an area where Python is somewhat different from other languages; in python, almost anything can be used in a boolean context like this. "if foo:" means "if foo is not empty".
  • Felix Kling
    Felix Kling over 10 years
    @dstromberg: That's why I said "How this exactly happens depends on the language."
  • Steinar Lima
    Steinar Lima over 10 years
    It is a bit more complicated than that, e.g '', empty lists and None (among others) is evaluated to False.
  • Ismail Badawi
    Ismail Badawi over 10 years
    This is not true. if day evaluates day in a boolean context -- it has nothing to do with None. Actually here it's checking for the empty string.
  • Siva Tumma
    Siva Tumma over 10 years
    do strings contain isdigit() method ?
  • Ismail Badawi
    Ismail Badawi over 10 years
    Yes. You can easily check this.
  • Siva Tumma
    Siva Tumma over 10 years
    And why are you expecting only strings will be passed as arguments to valid_day ?
  • Ismail Badawi
    Ismail Badawi over 10 years
    I didn't write this code. If e.g. a nonzero int is passed, an AttributeError will be raised. But the function is obviously expecting strings, or it wouldn't be calling isdigit.
  • Siva Tumma
    Siva Tumma over 10 years
    Empty string is almost equivalent to None though not. We check like if (param_value is None or param_value == ''): when we code for web server app that gets request parameters. But in general this style of coding means it is checking for None before making calls of an object's members (methods or member variables).
  • Stuart
    Stuart over 10 years
    @dstromberg if foo: in Python does not mean if foo is not empty. There are a number of ways that foo can be evaluated as False - see the other answers to this question.
  • Henrik
    Henrik over 10 years
    "I.e. there are language specific conversions from different types into a boolean." covers that, doesn't it?
  • Adam Smith
    Adam Smith over 10 years
    @IsmailBadawi, we don't need to check for the empty string in this context, as "".isdigit() will return False. It is, in fact, checking for None since None.isdigit() will throw an AttributeError as you correctly asserted.
  • Steinar Lima
    Steinar Lima over 10 years
    Sorry about that - i missed the for numeric values part of your answer :)
  • greggo
    greggo over 10 years
    It's not the same. Suppose day='Friday'. then if day will test as true, and if day == True will test as False; a non-empty string has a 'true' truth value, but all comparisions using == between a string and a boolen value will yield False; no string is equal to a boolean value.
  • greggo
    greggo over 10 years
    if day: is a short way of writing if bool(day): or, if you prefer (and I very much don't) if bool(day)==True:
  • greggo
    greggo over 10 years
    I've noticed that many programmers tend to have a style which is sort of 'in denial' of boolean expressions; they write if(boolvar==true) (I'm in C++ now) and, worse, if(x<0)is_neg = true; else isneg=false; I'm never sure whether they don't know that it can be simpler, or they just prefer it to be more complicated. Or maybe this is a style learned from other languages (fortran? matlab?) where you have to do these things?
  • greggo
    greggo over 10 years
    I read it that the function may be passed None -- to signify a missing day -- instead of string (and should just return None); so 'if day' is needed to avoid calling None.isdigit().
  • Ismail Badawi
    Ismail Badawi over 10 years
    Okay. My point was that if statements have nothing to do with None -- they just evaluate the expression in a boolean context, and None happens to be false in a boolean context. The answer makes it seem like None is treated specially.
  • Alcides
    Alcides over 10 years
    Thanks adsmith, your answer plus the other's answers and commentaries, give me a sense on what does that mean "if" applied to non-boolean (explicit) values. I've recently joined to this community and there is "a lot" of information and colaboration here. Thanks again!
  • Gojir4
    Gojir4 over 5 years
    This looks that the perfect way to check if a object is None, without using the ugly syntax if var is None, or even worst if var is not None.
  • greggo
    greggo over 5 years
    @Gojir4 what does? I haven't suggested any alternative and have in fact recommended against var==None. What's "ugly" about var is None, if that's what you want to test for?
  • Keith Hanlan
    Keith Hanlan over 2 years
    @greggo, it's not so much that "var is None" is ugly but rather that forgetting the "is None" is an easy mistake to make. Therefore, if one has a type that is nominally integer (or boolean for that matter) but may also be None, then it is best to implement __nonzero__.
  • greggo
    greggo over 2 years
    @KeithHanlan I'm not sure what you're saying. if var is None tests if var is the None object. Omit the is None and you're testing the truth-value of var, which is a different operation. No amount of implementing __nonzero__ can change that (you can only change what a class type defines to be its own truth value).
  • Keith Hanlan
    Keith Hanlan over 2 years
    @greggo, Sorry for the confusion. I meant to direct my comment to Gojir4 who referred to the "is None" syntax as "ugly". We are on the same page.