{"id":"classes-first-class","slug":"first-class","title":"Your first class","text":"So far you have used classes that come with Python, such as `Fraction` and `date`. Now you'll write your own. A class is defined with the keyword `class`, the class's name and a colon. What belongs to the class is indented under it, as in a function:\n\n```python\nclass Planet:\n    pass\n```\n\nThis class is empty: `pass` is the statement that does nothing, there because Python needs at least one line in the block. It already works as a blueprint, though.\n\nWhy a capital P? PEP 8 gives the names of new classes a look of their own, so that a reader can tell them apart from everything else. Compare `weather_station`, a variable or a function, with `WeatherStation`, a class: no underscores, and a capital letter at the start of every word. This style is called **PascalCase**. With it, `Planet()` reads as \"make a planet\", while `planet_count()` is a function call. (As you saw in the previous module, Python's built-in classes such as `int` and `list`, and some library classes such as `date`, have names in small letters. Your own classes should still follow the custom.)\n\n### Objects and their attributes\n\nTo make an object, call the class like a function. Then you can attach **attributes** to the object, its own variables, by assigning to them with a dot:\n\n```python\nclass Planet:\n    pass\n\n\nhome = Planet()\nhome.name = \"Earth\"\nhome.moons = 1\n\nred = Planet()\nred.name = \"Mars\"\nred.moons = 2\n\nprint(home.name, home.moons)\nprint(red.name, red.moons)\n```\n\n```output\nEarth 1\nMars 2\n```\n\nEach object has its own attributes: `home.name` and `red.name` are two different variables, one in each object. (As in the code above, PEP 8 asks for two blank lines around a class, as around a function.)\n\n### Always through the object\n\nAn attribute is stored inside its object, and the way to it goes through the object: the object's name, a dot, then the attribute's name. Leave out the object, and Python looks for an ordinary variable of that name instead:\n\n```python\nclass Planet:\n    pass\n\n\nhome = Planet()\nhome.moons = 1\nprint(home.moons)\nprint(moons)\n```\n\n```output\n1\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 8, in <module>\n    print(moons)\n          ^^^^^\nNameError: name 'moons' is not defined\n```\n\nThe program has no variable `moons`, only an object `home` with an attribute of that name. And since every `Planet` object can have moons of its own, a plain `moons` couldn't say whose moons you mean anyway.\n\nThe opposite mistake is asking an object for an attribute it doesn't have: one with a typo in its name, or one the program never gave to that object. Then you get the `AttributeError` you met in the previous module. Nothing in an empty class makes sure that every planet gets the same attributes. The next step shows how a class can take care of that itself.\n","task":"Fill in the blanks, so that the program defines the class `Robot`, makes an object of it and prints:\n\n```\nBolt 80\n```\n","kind":"fill","seed":"[[class]] Robot:\n    pass\n\n\nhelper = [[Robot()]]\nhelper.name = \"Bolt\"\nhelper.battery = 80\nprint(helper.name, helper.battery)\n","solution":"class Robot:\n    pass\n\n\nhelper = Robot()\nhelper.name = \"Bolt\"\nhelper.battery = 80\nprint(helper.name, helper.battery)\n","hints":["A class definition starts with the keyword that names what it defines.","The first blank is `class`. To make an object, call the class like a function: `Robot()`."],"tests":[{"name":"Output","stdin":"","expect":"Bolt 80","hidden":false}],"require":[],"forbid":[],"more":[{"task":"This program should print the owner of each bike and how many gears it has, but it stops with an `AttributeError` after the first line. Cy's bike has a single gear. Fix the program, so that it prints:\n\n```\nAda 21\nBen 7\nCy 1\n```\n","kind":"code","seed":"class Bike:\n    pass\n\n\nroad = Bike()\nroad.owner = \"Ada\"\nroad.gears = 21\n\ncity = Bike()\ncity.owner = \"Ben\"\ncity.gear = 7\n\nkids = Bike()\nkids.owner = \"Cy\"\n\nfor bike in [road, city, kids]:\n    print(bike.owner, bike.gears)\n","solution":"class Bike:\n    pass\n\n\nroad = Bike()\nroad.owner = \"Ada\"\nroad.gears = 21\n\ncity = Bike()\ncity.owner = \"Ben\"\ncity.gears = 7\n\nkids = Bike()\nkids.owner = \"Cy\"\nkids.gears = 1\n\nfor bike in [road, city, kids]:\n    print(bike.owner, bike.gears)\n","hints":["Check it and read the error: it names the attribute that one of the bikes doesn't have, and Python even guesses what was meant. The line printed before it shows which bike was fine.","Ben's bike got its gears under a misspelled name, `gear`. The loop asks every bike for `gears`.","Once that's fixed, the error comes back for the third bike, which never got gears at all. Give it the attribute too."],"tests":[{"name":"Output","stdin":"","expect":"Ada 21\nBen 7\nCy 1","hidden":false}],"require":[],"forbid":[]},{"task":"Write an empty class `Song` and a function `make_song(title, artist, seconds)` that makes a new `Song` object, attaches the attributes `title`, `artist` and `seconds` to it, and returns the object.\n\nThis code:\n\n```python\nsong = make_song(\"Rainy Bus Stop\", \"The Umbrellas\", 214)\nprint(song.title)\nprint(song.artist, song.seconds)\n```\n\nprints\n\n```\nRainy Bus Stop\nThe Umbrellas 214\n```\n","kind":"code","seed":"# Write the class Song here.\n\n\ndef make_song(title, artist, seconds):\n    pass\n\n\nif __name__ == \"__main__\":\n    song = make_song(\"Rainy Bus Stop\", \"The Umbrellas\", 214)\n    print(song.title)\n","solution":"class Song:\n    pass\n\n\ndef make_song(title, artist, seconds):\n    song = Song()\n    song.title = title\n    song.artist = artist\n    song.seconds = seconds\n    return song\n\n\nif __name__ == \"__main__\":\n    song = make_song(\"Rainy Bus Stop\", \"The Umbrellas\", 214)\n    print(song.title)\n","hints":["The class needs only two lines: `class Song:` and an indented `pass`.","In the function, make the object with `song = Song()`, then set each attribute: `song.title = title`, and so on.","Return the object itself at the end, not one of its attributes."],"tests":[{"name":"Test 1","stdin":"","call":"song = make_song(\"Rainy Bus Stop\", \"The Umbrellas\", 214)\nprint(song.title)\nprint(song.artist, song.seconds)\n","expect":"Rainy Bus Stop\nThe Umbrellas 214","hidden":false},{"name":"Test 2","stdin":"","call":"first = make_song(\"Lighthouse\", \"Kai Noor\", 187)\nsecond = make_song(\"Static\", \"Volt Sisters\", 245)\nprint(second.title, second.artist, second.seconds)\nprint(first.title, first.artist, first.seconds)\n","expect":"Static Volt Sisters 245\nLighthouse Kai Noor 187","hidden":true}],"require":[{"pattern":"\\bclass\\s+Song\\b","message":"Define the class with `class Song:`."}],"forbid":[]}]}