Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

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.

Avatar image for user45755

user45755 on Sept. 29, 2021

Lost me at the end

Avatar image for Bartosz Zaczyński

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?

Avatar image for DimaG

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))
Avatar image for Bartosz Zaczyński

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 uses field() (and radians(), sin(), cos(), asin(), sqrt() inside .distance()), so you’d need something like from dataclasses import dataclass, field and from math import radians, sin, cos, asin, sqrt for it to run.
  • The example builds a Position, so it doesn’t actually exercise the subclass part. To see the payoff, you’d instantiate Capital with 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.