In the libraries session you wrote a line that was quietly teaching you something bigger than it looked. Here it is again:
from datetime import date
deadline = date(2026, 11, 1)
today = date.today()
print((deadline - today).days)Look at that last line. You subtracted two dates. And here is the thing nobody stopped to point out: deadline - today did not hand you back a plain number. If it had, you'd have written print(deadline - today) and been done. Instead you had to reach in and ask it for .days.
That's because subtracting two dates gives you back a gap — a little package that knows the distance between two days. To get the number of days out of it, you ask the gap: .days. You already did this. You already own the whole idea. Let me just give it a name.
Two kinds of thing come back
You know by now that a function hands something back. statistics.mean(scores) hands back a number. input("Name: ") hands back a string. Those are plain values — you print them, you store them, you move on.
But sometimes a function hands you back a thing instead. Not a number, not a string — a thing with its own tools attached. And the way you use those tools is the same dot you already know.
The gap between two dates was your first one. You made the gap, then you reached into it with a dot and asked for .days. Make the thing, then use the dot. Hold onto that shape, because it repeats everywhere.
Example: you get an image back
There's a small library called qrcode. Its whole job is to turn a link into one of those square black-and-white codes. You'd install it once with !pip install qrcode, then use it like this:
import qrcode
img = qrcode.make("https://my-application-portal.org")
img.save("application_qr.png")Read that slowly. qrcode.make(...) didn't hand you a number or a string. It handed you back an image — and you caught it in img.
Now img is a thing sitting in your hands. What can you do with it? You reach in with the dot and tell it: img.save("application_qr.png"). You're not asking it a question this time — you're giving it an instruction. Save yourself, under this name. And it does.
Same dot as statistics.mean. The only difference is what's on the left of it. Before, the thing on the left was a box's name — statistics. Now the thing on the left, img, came out of a function.
Example: you get a file back
Here's the same shape one more time, and this one you have definitely done already:
f = open("shortlist.txt", "w")
f.write("Fulbright\n")
f.write("Chevening\n")
f.close()open(...) doesn't hand you back the text of a file. It hands you back the file itself, opened and waiting. You catch it in f. Then you reach in with the dot, over and over — f.write(...) to put a line in, f.close() to shut it when you're done. Tell it, tell it, tell it. Every one of those is the dot you already know.
Nobody made a fuss about it at the time. We just opened a file. But it was the same move, and you did it without blinking.
The whole pattern, in one line
Here's the shape underneath all three:
Make the thing. Then use the dot to ask it for something, or tell it to do something.
That's it. (deadline - today) was the thing — you asked it for .days. img was the thing — you told it to .save(...). f was the thing — you told it to .write(...) and to .close().
It is the exact same dot from statistics.mean(scores). The only new part is that the thing on the left of the dot came out of a function, instead of being a library's name. That's the entire lesson. You already knew nine-tenths of it before you read this.
Common slip-ups
-
Not catching the thing. If you write
qrcode.make(link)on its own line and then wonder where your image went — it went nowhere. The function handed you an image and you didn't catch it. You needimg = qrcode.make(link)so you have something to reach into afterward. A thing you don't store is a thing you can't use. -
Forgetting
.save()needs a name.img.save()with empty brackets won't work — the image has no idea what to call the file. It needsimg.save("application_qr.png"). When you tell a thing to save itself, you have to tell it under what name. -
The name you install is not always the name you import. Plenty of libraries are installed under one word and imported under another. So
!pip installfinishes happily, you writeimport, and Python tells you there is no such thing. That is not you being stupid — that is the library having two names. When it happens, find the library's own "getting started" page and copy its first two lines exactly.
Next time a line of code hands you something back and you're not sure what to do with it, try the dot. Ask it for something. Tell it to do something. Most of the time, the thing already knows how.