Check your understanding of the previous reading: chained attribute access on nested dataclasses, the order of definitions, and temporary variables.

Question 1

Given the following code…

from dataclasses import dataclass

@dataclass
class Location:
    city: str
    state: str

@dataclass
class Trip:
    origin: Location
    destination: Location
    duration: int

my_trip = Trip(Location("Newark", "DE"),
               Location("Baltimore", "MD"),
               90)

What will each of the following expressions produce?

#ExpressionProduces
1 my_trip[0].state
2 my_trip.origin.state
3 my_trip.duration
4 my_trip.destination.city
5 Trip.Location.state
6 my_trip.origin.city[0]

Question 2

Which of the following statements about the order of definitions is NOT correct?

Select one answer, then check.

  • Not quite: this statement is correct. The field annotation in A names B, so B must already exist when A is defined; otherwise a NameError occurs, as in the reading's Order of Definitions example.
  • Not quite: this statement is correct. The header of X names A as its return type, and the reading's rule is that a dataclass has to be defined before anything refers to it.
  • Correct: this statement is not correct. A call inside the body of X only runs when X is called, so Y just has to exist by then; X and Y can be defined in either order, as long as both come before the call to X.
  • Not quite: this statement is correct. Calling the constructor A(...) before the class is defined raises a NameError.
  • Not quite: this statement is correct. Calling a function before its def has run raises a NameError.
  • Not quite: this statement is correct. Reading a variable before it has been assigned raises a NameError.

Question 3

Which of the following can be iterated over directly with a for loop?

Select every answer that applies, then check.

  • True. Iterating over a string gives its characters one at a time.
  • Not true. An integer is a single value; for x in 5: raises a TypeError.
  • Not true. You access the fields of an instance by name, one at a time; a for loop over the instance itself raises a TypeError. A list field inside the instance can be iterated over.
  • True. Iterating over a list gives its elements one at a time.

Question 4

Given the following code:

from dataclasses import dataclass

@dataclass
class Position:
    x: int
    y: int

@dataclass
class Rectangle:
    start: Position
    end: Position
    color: str

@dataclass
class Button:
    box: Rectangle
    text: str

@dataclass
class World:
    save: Button
    load: Button

Assuming we had an instance of a World stored in a variable named world, what expression would correctly access the World's Save button's starting X coordinate?

Show worked solution

Start from world and follow one field at a time: world.save is the Save Button, .box is its Rectangle, .start is that rectangle's starting Position, and .x is its X coordinate. Together: world.save.box.start.x.

Question 5

Given the following code:

from dataclasses import dataclass

@dataclass
class Location:
    city: str
    state: str

@dataclass
class Trip:
    origin: Location
    destination: Location
    duration: int

my_trip = Trip(Location("Newark", "DE"),
               Location("Baltimore", "MD"),
               90)

Which of the following code blocks will print the text DE?

Select every answer that applies, then check.

  • True. my_origin is a temporary variable holding the origin Location, and its state is "DE".
  • Not true. state on its own is not a variable, so the second line raises a NameError.
  • True. The temporary variable holds the string "DE" itself.
  • Not true. The first line evaluates "DE" but doesn't store or print it; print() prints an empty line.
  • True. The chained access goes from the trip to its origin to its state, "DE".
  • Not true. The chain is in the wrong order: a Trip has no state field, so this raises an AttributeError.
  • Not true. Trip is the class, not the instance my_trip; it holds no origin value, so this raises an AttributeError.