hexerous
hexerous

Reputation: 251

What does adding '().days' in a variable work?

So I am doing a course on Python and was on a chapter quiz. The first time I answered the question, I was wrong, then I saw the actual answer. The two unknown's were (bday-today).days. Additionally, I also want to know how "Birthday in %d days" % (diff+365) works.

Here's the code:

from datetime import *

def main():
    today=date.today()
    bday=date(today.year,12,13)
    diff=(bday-today).days
    if diff>0:
     print("Birthday in %d days" % diff)
    else:
     print("Birthday in %d days" % (diff+365))

main()

Upvotes: 1

Views: 94

Answers (2)

J-L
J-L

Reputation: 1901

As for (bday-today).days, it often surprises people when they see a method called on an expression like (a + b). It doesn't make sense that (a + b).method() could ever work.

However, you're not calling .method() on the parentheses; you're calling it on the result of a + b, which should be an object that supports calling .method().

Consider this code:

a = "Hello, "
b = "World!"

What if you want to find the length of the combined string? Well, you could do this:

c = a + b
print( len(c) )

But you can save a step with:

print( len(a + b) )

This probably doesn't surprise you too much, but let's change the question a little bit:

What if you wanted the upper-case equivalent of the combined string? Well, you could write:

c = a + b
print( c.upper() )

Or, you could save a step and do:

print( (a + b).upper() )

Because you may have never seen a parenthesized expression having a method called on it, this may look bizarre to you. But all that's happening is that (a + b) is creating a new object (which is a str object), which then gets its .upper() method called.

You may (or may not) have even seen code like this:

some_function().some_action()

That looks wrong, but is it? It looks like we're calling a method of a function!

But we're not. What's really going on is that some_function() is returning an object, and this object has a .some_action() method that can be called. Basically, the above code is really no different than:

var = some_function()
var.some_action()

(except that the returned value of some_function() is not stored off in a variable).

And this isn't a Python quirk; this behavior is found in C++, Java, and pretty much every other Obejct-Oriented language there is.

(Don't feel bad if you didn't know about this. I worked with a professional C++ programmer (with over a decade of experience) who didn't know that that was possible in C++. When I explained to him that it worked, he thought it was best to "play it safe" and not use that construct -- because, you know, "the compiler might not support it!" However, this must be supported by Object-Oriented languages -- otherwise, a fundamental property of OO is broken -- namely, that objects (even returned objects) can have their methods called.)


As for "Birthday in %d days" % (diff+365), it's an old way of formatting text that's been replaced by f-strings and the str.format(). Basically, these lines are equivalent:

"Birthday in %d days" % (diff+365)   # Usually found in Python 2.X
"Birthday in {} days".format(diff+365)  # Usually found in Python 3.X
f"Birthday in {diff+365} days"   # Usually found in Python 3.X

If you're used to programming in Python 3.X, it's no surprise that it looks unfamiliar to you. I recommend reading up a little on it (so you can recognize if for what it is), but using the other format methods when writing your own code.

Upvotes: 4

tobias_k
tobias_k

Reputation: 82899

The line diff = (bday - today).days gets the difference between bday and today, which is an instance of datetime.timedelta, and then gets the days attribute from that timedelta, and thus the number of days until (or since) the birthday. The parens are necessary, since without, bday - today.days would be evaluated as bday - (today.days), which would not make sense.

Similarly, "Birthday in %d days" % (diff+365) is basically just the same as two lines above, but adding 356 to the number of days before putting them where the %d is in the string. Again, the parens are necessary since % is technically still a "multiplication/division" type operation, even though it is used differently here, and thus stronger binding than addition, i.e. without it would be evaluated as ("Birthday in %d days" % diff) + 365, which, again, would not make sense.

Upvotes: 1

Related Questions