Think You Know Python? The Class Variable Brain Teaser That Trips Up Seniors
I love a good brain teaser, and this one has tripped up surprisingly experienced Python developers. It touches on a core concept of the language that is easy to forget when you are moving fast.
Take a look at the Python snippet below. Without running the code in your IDE, try to figure out what the exact output of the three print statements will be.
The Challenge
class Developer:
skill_level = 1
languages = []
class FrontendDev(Developer):
pass
class BackendDev(Developer):
pass
# Let's make some changes
FrontendDev.skill_level = 2
FrontendDev.languages.append('JavaScript')
BackendDev.skill_level = 3
BackendDev.languages.append('Python')
Developer.languages.append('SQL')
# What gets printed?
print(f"Dev: {Developer.skill_level}, {Developer.languages}")
print(f"Front: {FrontendDev.skill_level}, {FrontendDev.languages}")
print(f"Back: {BackendDev.skill_level}, {BackendDev.languages}")
Do you have your answer? Drop your guess in the comments below before you check the solution! Bonus points if you can explain why it behaves this way.
The Solution
🚨 Click here to reveal the output and explanation
The Output:
Dev: 1, ['JavaScript', 'Python', 'SQL']
Front: 2, ['JavaScript', 'Python', 'SQL']
Back: 3, ['JavaScript', 'Python', 'SQL']
Why does this happen?
It comes down to how Python handles mutable vs. immutable class variables:
- Integers are immutable: When we assign
FrontendDev.skill_level = 2andBackendDev.skill_level = 3, Python creates entirely new attributes in the specific namespaces of theFrontendDevandBackendDevclasses. It does not overwrite the parentDeveloper.skill_level, which safely remains1. - Lists are mutable: The
languageslist is defined at the class level onDeveloper. BecauseFrontendDevandBackendDevinherit fromDeveloperand don't explicitly overwrite the list with a brand new assignment (e.g.,FrontendDev.languages = []), calling.append()on the children modifies the exact same list object residing in the parent class's memory space.
Therefore, all three .append() calls are adding strings to the exact same underlying list, while the integers remain isolated to their respective child classes.
Did you get it right? Let me know in the comments!
No comments:
Post a Comment