Remember that a class is itself an object, and has its own attributes. So we have two simple cases, and then one that’s slightly more complicated. Here’s a bit of a breakdown:
class Demo:
cls_int = 42
cls_list = ["hello"]
def __init__(self):
self.inst_int = 123
self.inst_list = ["goodbye"]
demo_instance = Demo()
Okay. So we have two attributes on the class, and two on the instance. One’s an immutable integer, the other’s a mutable list. Let’s look at the two easy cases first.
print(Demo.cls_int, Demo.cls_list)
print(demo_instance.inst_int, demo_instance.inst_list)
Demo.cls_int = 142857
Demo.cls_list.append("world")
demo_instance.inst_int = 314159
demo_instance.inst_list.append("felicia")
All of this should be completely unsurprising. When you either read from or assign to an attribute of some object - even if that object happens to be a class - it’s going to behave just the way you expect it to.
The less obvious situation, though, is that an instance can see class attributes. Let’s start with read-only usage:
print(demo_instance.cls_int, demo_instance.cls_list)
# Prints out 142857 and ["hello", "world"] if you did the above
# mutations, otherwise 42 and ["hello"]
However, any time you assign, it goes to the instance.
demo_instance.cls_int = 271828
print(Demo.cls_int, demo_instance.cls_int)
# Prints 142857 and 271828
You now should have all the tools you need to work through these questions.
- What happens if you do
demo_instance.cls_list.append("!")
? Which list is mutated?
- If you did the assignment of cls_int to 271828, do
del demo_instance.cls_int
. Now, what happens if you do demo_instance.cls_int = demo_instance.cls_int + 1
? Remember, it’s a lookup (and the attribute won’t exist on the instance), followed by an assignment.
- Delete the attribute again if you need to. What does
demo_instance.cls_int += 100
do? How does the +=
operator work with integers?
- Now for a tricky one.
a. print(demo_instance.cls_list)
b. demo_instance.cls_list += ["Wut"]
c. print(demo_instance.cls_list)
d. print(Demo.cls_list)
What has happened after step 4? Which object(s) have an attribute named cls_list
? What do those attributes contain? This is a bit tricky, so feel free to play around in the REPL and try to figure it out. Hint: You can check what attributes something has with the dir()
function, and make use of the is
operator to see whether two objects are actually the same object.
Bonus challenge: What would be different if, instead of a ilst, we’d used a tuple? You can demo_instance.cls_tuple += ("Wut?",)
to have the same effect as the list concatenation. How would that change what happens here?
(Edit: Fixed a bug in the question.)