A name is a label, not a box
In C, int a = 5; reserves 4 bytes and writes 5 into them. In Python, a = 5 creates an integer object with the value 5 and sticks the label a on it. The difference shows up here.
a = 5
b = a
a = 7
print(b) # 5, not 7
b = a copied the label, not the value. Both labels pointed at the same 5. Then a was moved to point at a 7. The 5 never changed, because integers in Python cannot be changed. They are immutable.
The four types you will use every day
| Type | Example | What it holds |
|---|---|---|
int |
42, -7, 10**30 |
Whole numbers, any size |
float |
3.14, 2.0, 1e-6 |
Numbers with a decimal point |
str |
"BTech", 'a' |
Text |
bool |
True, False |
Yes or no |
The int row is worth stopping on. A 32-bit int in C holds up to 2,147,483,647. Add one and it wraps around to -2,147,483,648. Python has no such limit.
print(2 ** 100)
# 1267650600228229401496703205376
Python grows the integer as needed, using more memory. That is why Python never overflows and C does.
Floats do not do what you expect
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
This is not a Python bug. A float stores a number in binary, and 0.1 in binary is a repeating fraction, exactly like 1/3 is 0.3333... in decimal. It gets cut off, so a tiny error remains. Every language with floats has this, C included.
Never compare two floats with ==. Compare the difference to a small tolerance instead: abs(x - y) < 1e-9. Numerical methods questions in your exams often hide a mark here.
Conversion, and the input() trap
n = input("Enter a number: ")
print(type(n)) # <class 'str'> - always a string
input() gives you a string every single time, even if the user typed 42.
n = int(input("Enter a number: "))
print(n * 2)
Wrap it in int() or float(). If you forget, n 2 with n = "42" does not give 84 - it gives "4242", because on a string repeats it. That silent wrong answer is worse than a crash.
int("42") works. int("42.5") raises ValueError. If the user might type a decimal, use float() first: int(float("42.5")) gives 42.
Operators that are not obvious
print(7 / 2) # 3.5 true division, always a float
print(7 // 2) # 3 floor division, throws away the remainder
print(7 % 2) # 1 remainder
print(7 ** 2) # 49 power
print(-7 // 2) # -4 floors downward, not toward zero
That last line catches people. C's integer division truncates toward zero, so -7 / 2 is -3 in C. Python floors, so it is -4. If you are converting a C algorithm to Python and the numbers go wrong at negative values, this is usually why.
f-strings
The old way of building output was clumsy. This is the modern way.
name = "Ananya"
cgpa = 8.7346
sem = 3
print(f"{name} is in semester {sem} with CGPA {cgpa:.2f}")
# Ananya is in semester 3 with CGPA 8.73
Put f before the quote, then put any expression inside {}. The :.2f after the colon is a format spec: show it as a float with 2 decimal places.
More specs worth memorising:
value = 1234.5678
print(f"{value:.1f}") # 1234.6
print(f"{value:10.2f}") # 1234.57 padded to width 10
print(f"{value:,.2f}") # 1,234.57 thousands separators
print(f"{42:05d}") # 00042 zero padded
print(f"{0.256:.1%}") # 25.6% as a percentage
You can put real expressions inside the braces, not just names.
marks = [72, 65, 88]
print(f"Average: {sum(marks) / len(marks):.2f}")
# Average: 75.00
Naming
Python's convention is lower_case_with_underscores for variables and functions, ALL_CAPS for constants. Follow it. avgMarks works but marks you out as someone who learned Java first, and in a code review that is the first thing anyone says.
Names cannot start with a digit, cannot contain spaces, and must not shadow built-ins. Naming a variable list or sum or input is legal and will break the rest of your program in a way that is very hard to find.