Inheritance and Subclassing
00:00
Inheritance. You can subclass data classes quite freely. As an example, we’ll extend our Position data class with a country field to record capitals.
00:37
In this simple example, everything works without a hitch. The country field of Capital is added after the three original fields in Position. Things get a little more complicated if any fields in the base class have default values.
01:25
This code will generate a TypeError complaining that non-default argument 'country' follows default argument. The problem is that our new country field has no default value, while the lon and lat fields have default values.
01:41 The data class will try and write the code seen onscreen, and this is not valid Python. If a parameter has a default value, all following parameters must also have default values.
01:55 In other words, if a field in a base class has a default value, then all new fields added in a subclass must have default values as well. Another thing to be aware of is how fields are ordered in a subclass.
02:09
Starting with the base class, fields are ordered in the order in which they are first defined. If a field is redefined in a subclass, its order doesn’t change. For example, if you define Position and Capital as seen onscreen,
02:52
then the order of the fields in Capital will still be name, lon, lat, country. However, the default value of lat will be 40.0.
03:11 In the next section of the course, you’ll take a look at how to make data classes faster and use less memory.
Bartosz Zaczyński RP Team on Sept. 29, 2021
@user45755 Feeling lost is a good sign. It means that you’re learning 😉 Which part of the lesson did you find problematic, specifically?
DimaG on July 2, 2026
If you set kw_only field to True in the @dataclass decorator in both parent and subclass, then you don’t have to make sure that all new fields have default value. kw_only=True not only makes sure you use keyword arguments when setting instances of the class, but also marks all instance fields as keyword arguments whether they have default values or not.
from dataclasses import dataclass
@dataclass(slots=True, kw_only=True)
class Position:
name: str
lon: float = field(default=0.0, metadata={"unit": "degrees"})
lat: float = field(default=0.0, metadata={"unit": "degrees"})
def distance(self, other):
earth_radius = 6371
lam_1, lam_2 = radians(self.lon), radians(other.lon)
phi_1, phi_2 = radians(self.lat), radians(other.lat)
h = (
sin((phi_2 - phi_1) / 2) ** 2
+ cos(phi_1) * cos(phi_2) * sin((lam_2 - lam_1) / 2) ** 2
)
return 2 * earth_radius * asin(sqrt(h))
@dataclass(slots=True, kw_only=True)
class Capital(Position):
country: str
oslo = Position(name="Oslo", lon=10.8, lat=59.9)
vancouver = Position(name="Vancouver", lon=-123.1, lat=49.3)
print(oslo.distance(vancouver))
Bartosz Zaczyński RP Team on July 5, 2026
@DimaG True, and it’s a clean way to sidestep the ordering rule the lesson runs into. Since kw_only=True makes every field keyword-only, the “non-default argument follows default argument” restriction no longer applies, so Capital can add a required country with no default of its own. That was added in Python 3.10, so it’s a nice modern alternative to giving every subclass field a default.
A couple of small things on the snippet, in case someone copies it to try out:
- The paste only imports
dataclass, but it also usesfield()(andradians(),sin(),cos(),asin(),sqrt()inside.distance()), so you’d need something likefrom dataclasses import dataclass, fieldandfrom math import radians, sin, cos, asin, sqrtfor it to run. - The example builds a
Position, so it doesn’t actually exercise the subclass part. To see the payoff, you’d instantiateCapitalwith the extra required field:
oslo = Capital(name="Oslo", lon=10.8, lat=59.9, country="Norway")
Without kw_only=True, that same Capital definition raises TypeError: non-default argument 'country' follows default argument, which is exactly the problem the lesson describes.
One trade-off worth flagging: kw_only=True means callers have to pass everything by keyword, so Position("Oslo", 10.8, 59.9) stops working and you have to name the arguments. That’s often what you want with a wide dataclass, but it is a behavior change rather than a free win. The lesson’s approach of giving the new fields default values still works too, so it comes down to whether you’d rather invent defaults or require keywords.
Thanks for adding this 🙂
Become a Member to join the conversation.

user45755 on Sept. 29, 2021
Lost me at the end