I Asked 20 Python Developers to Trace This Code. 18 Got It Wrong.

작성자

카테고리:

← 피드로
DEV Community · Ameer Abdullah · 2026-07-22 개발(SW)
Cover image for I Asked 20 Python Developers to Trace This Code. 18 Got It Wrong.

Ameer Abdullah

I shared this code with 20 developers ranging from students to people with three or more years of experience. I asked them to write down the output before running it.

18 of them got it wrong.

class Config:
    settings = {}

    def add(self, key, value):
        self.settings[key] = value

c1 = Config()
c2 = Config()

c1.add("theme", "dark")
c2.add("language", "Python")

print(c1.settings)
print(c2.settings)

Enter fullscreen mode Exit fullscreen mode

Take a moment. What do you think both lines print?

What Most People Predicted

The most common answer was:

{'theme': 'dark'}
{'language': 'Python'}

Enter fullscreen mode Exit fullscreen mode

The logic: c1 and c2 are separate objects, so their settings should be separate.

What It Actually Prints

{'theme': 'dark', 'language': 'Python'}
{'theme': 'dark', 'language': 'Python'}

Enter fullscreen mode Exit fullscreen mode

Both instances share the same dictionary. Adding to c2 also affected c1.

Why This Happens

settings = {} is a class variable. It is defined on the Config class itself, not on any instance.

When you write self.settings[key] = value, Python looks up self.settings. It checks the instance’s __dict__ first. Finding no settings attribute there, it looks at the class. It finds Config.settings which is the shared dictionary.

It then calls dict.__setitem__ on that shared dictionary. This mutates the shared object. Both c1 and c2 read from the same dictionary so both see all additions.

The Fix: Move to init

class Config:
    def __init__(self):
        self.settings = {}

    def add(self, key, value):
        self.settings[key] = value

c1 = Config()
c2 = Config()

c1.add("theme", "dark")
c2.add("language", "Python")

print(c1.settings)
print(c2.settings)

Enter fullscreen mode Exit fullscreen mode

Output:

{'theme': 'dark'}
{'language': 'Python'}

Enter fullscreen mode Exit fullscreen mode

Moving settings = {} into __init__ creates a new dictionary for each instance. self.settings in __init__ creates an instance attribute that shadows any class attribute of the same name.

Why This Pattern Appears in Interviews

This question reveals whether a candidate understands the difference between class attributes and instance attributes at the level of Python’s actual object model.

Writing a class is easy. Understanding how Python resolves attribute access through the instance’s __dict__ first and then the class is the underlying knowledge being tested.

The follow-up question is always: “What if settings were a string instead of a dict? Would the behavior be different?”

class Config:
    name = "default"

    def set_name(self, new_name):
        self.name = new_name

c1 = Config()
c2 = Config()

c1.set_name("custom")
print(c1.name)
print(c2.name)

Enter fullscreen mode Exit fullscreen mode

Output:

custom
default

Enter fullscreen mode Exit fullscreen mode

With a string, self.name = new_name creates a new instance attribute on c1 that shadows the class attribute. c2 has no instance attribute so it still reads the class attribute "default".

With a dict, self.settings[key] = value mutates the existing class attribute through the reference. It never creates an instance attribute.

Mutation versus rebinding. The same distinction that explains list and integer += behavior.

For more class tracing problems, try PyCodeIt.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다