Python

OOP: Classes & Inheritance

37 flashcards · answers and spaced-repetition review in the KnowCard app

In a class, what must the first parameter of every (instance) method be, and what is passed into it?
What happens when you run this? ``` class Account: def show(): print("hi") Account().show() ```
Where should a class's instance attributes be created, and with what syntax?
Is __init__ a constructor in the strict sense, and what does it return?
What does this print? ``` class C: def __init__(self): print("init") x = C() ```
How does Python clean up an instance at the end of its life — is there a guaranteed destructor?
How do you make class B inherit from class A in Python?
What does this print? ``` class A: def __init__(self): self.x = 1337 def m(self): print(self.x) class B(A): pass B().m() ```
What does this print? ``` class A: def __init__(self): self.x = 1337 def m(self): print(self.x) class B(A): def __init__(self): self.y = 10000 B().m() ```
Inside a subclass's __init__, how do you also run the base class's constructor, and why is it needed?
What does this print? ``` class A: def m(self): print("A.m") class B(A): def m(self): print("B.m") super().m() B().m() ```
Besides super().__init__(), what is the other way to call a base class's overridden method, and what's the catch?
What does this print? ``` class Animal: def __init__(self, name): self.name = name class Dog(Animal): def __init__(self, name): super().__init__(name) self.legs = 4 d = Dog("Rex") print(d.name, d.legs) ```
Why prefer isinstance(x, Account) over type(x) == Account when checking an object's type?
What's the difference between isinstance() and issubclass(), and what do their arguments expect?
What is the ultimate base class of every class in Python, even one written class A: with no parents?
How do you let one class inherit from several base classes, and how is a name conflict resolved?
In multiple inheritance, which class does a method get resolved from — just the listed parents?
What does this print? (the diamond) ``` class A: def m(self): print("A") class B(A): def m(self): print("B"); super().m() class C(A): def m(self): print("C"); super().m() class D(B, C): def m(self): print("D"); super().m() D().m() ```
What goes wrong here with two unrelated parents? ``` class Offroad: def drive(self): print("land") class Watercraft: def drive(self): print("water") class Amphib(Offroad, Watercraft): pass Amphib().drive() ```
What's the practical difference between __str__ and __repr__ — which does print() use and which does the REPL / a list show?
What does this print? ``` class P: def __repr__(self): return "P()" print([P(), P()]) ```
At runtime you only have an attribute's name as a string. How do you read its value safely, and how do you just test whether it exists?
What does the @ operator do in Python, and since which version has it existed?
A class defines no __bool__ but defines __len__ that returns 0. Is an instance truthy? What if it defines neither method?
How do you create or delete an instance attribute when its name is computed as a string, e.g. building x0..x9 in a loop?
Can you subclass a built-in type like list or dict, and why is that even possible in Python?
What makes a method a 'magic' (dunder) method, and how is it normally invoked?
You want your object to be usable as a sequence index (e.g. in slicing). Which method must it implement, and what must that method return?
You want instances of your class to work as dict keys or set members. What must you implement, and what constraints does the hash have to satisfy?
How do you make + and - work on your own class, and what does a + b actually translate to under the hood?
Forget which function calls which — what should the content of __repr__ vs __str__ actually look like?
What does defining __call__ on a class let you do with its instances, and how would you use it?
Compare __getattr__ and __getattribute__: when is each triggered when you read an attribute?
Why does self.x inside __getattribute__ (or self.x = v inside __setattr__) hang the program, and what's the correct fix?
Normally you can tack new attributes onto an instance at runtime. What backs that ability, what does it cost, and how does __slots__ change it?
Inside a binary operator method like __add__, what should you return when the other operand is a type you can't handle — and what's the naming trap?

Start learning today

Free to start — download the app or use it in your browser.

Get it on App StoreGet it on Google Play