diff --git a/curriculum/challenges/_meta/lecture-classes-and-objects/meta.json b/curriculum/challenges/_meta/lecture-classes-and-objects/meta.json index 810c493d0b6..aae0c4606ac 100644 --- a/curriculum/challenges/_meta/lecture-classes-and-objects/meta.json +++ b/curriculum/challenges/_meta/lecture-classes-and-objects/meta.json @@ -5,6 +5,19 @@ "blockType": "lecture", "blockLayout": "challenge-list", "superBlock": "full-stack-developer", - "challengeOrder": [{ "id": "68420bd261d0d35f61922d4b", "title": "Step 1" }], + "challengeOrder": [ + { + "id": "68420bd261d0d35f61922d4b", + "title": "How Do Classes Work and How Do They Differ From Objects?" + }, + { + "id": "6874b5fc38f90f25e18093ce", + "title": "What Are Methods and Attributes, and How Do They Work?" + }, + { + "id": "6874b7d3b286c538b39d0c25", + "title": "What Are Special Methods and What Are They Used For?" + } + ], "helpCategory": "Python" -} +} \ No newline at end of file diff --git a/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/68420bd261d0d35f61922d4b.md b/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/68420bd261d0d35f61922d4b.md index 88cb7c6f585..50a72f7db73 100644 --- a/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/68420bd261d0d35f61922d4b.md +++ b/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/68420bd261d0d35f61922d4b.md @@ -1,137 +1,220 @@ --- id: 68420bd261d0d35f61922d4b -# title needs to be updated to correct title when lectures are finalized -title: Classes and Objects -# change back to 11 when video is added +title: How Do Classes Work and How Do They Differ From Objects? challengeType: 19 -# videoId: new-id-goes-here-when-ready -# dashedName needs to be updated to correct title when lectures are finalized -dashedName: lecture-classes-and-objects +dashedName: how-do-classes-work-and-how-do-they-differ-from-objects --- # --description-- -Watch the video or read the transcript and answer the questions below. +In Python, classes and objects work hand in hand to organize and manage data. You build a class to define shared behavior, then create objects that use those behaviors. + +In other words, a class is like a blueprint or template you use to create objects with. + +Let's look at what classes are, and how to use them to create objects. + +To create a class, you use the `class` keyword followed by the name of the class and a colon. Then within the class, you can add an initializer, along with any attributes and methods. + +Attributes are like variables within a class, and are used to store data. Methods are functions defined within a class, and are the actions objects created with a class can perform. + +Here's the basic syntax of a class: + +```python +class ClassName: + def __init__(self, name, age): + self.name = name + self.age = age + + def sample_method(self): + print(self.name.upper()) +``` + +* `class ClassName` is made up of the `class` keyword to create a class, followed by the name of the class, here called `ClassName`. It is common in Python to use the **PascalCase** convention when naming classes. + +* `def __init__(self, name, age)` is the special method automatically called when a new object is created. It initializes the attributes of the objects that will be created with the class. + + In addition to that, the first parameter of `__init__` is always a reference to the specific object being created or used. By convention, this parameter is named `self`, but technically, you can use any name. `self` lets you access the object's own attributes and methods. + +* `self.name = name` and `self.age = age` are the attributes the objects will have. + +* `def sample_method(self):` is the method each object created can call. + +* `print(self.name.upper())` is what the `sample_method` method will do, in this case, it prints the name in uppercase. + + +If that all sounds like a lot, don't worry. Let's take a look at a similar example of a `Dog` class, and how you can create objects from that: + +```python +class Dog: + def __init__(self, name, age): + self.name = name + self.age = age + + def bark(self): + print(f"{self.name.upper()} says woof woof!") +``` + +With this `Dog` class, you can create an object. Here's the basic syntax for creating objects from a class: + +```python +object_1 = ClassName(attribute_1, attribute_2) +object_2 = ClassName(attribute_1, attribute_2) +``` + +You can also call any of the methods defined in the class from each object: + +```python +object_1.method_name() +object_2.method_name() +``` + +Now let's create two dogs by using the `Dog` class as the blueprint: + +```python +class Dog: + def __init__(self, name, age): + self.name = name + self.age = age + + def bark(self): + print(f"{self.name.upper()} says woof woof! I'm {self.age} years old!") + +dog_1 = Dog("Jack", 3) +dog_2 = Dog("Thatcher", 5) + +# Call the bark method +dog_1.bark() # JACK says woof woof! I'm 3 years old! +dog_2.bark() # THATCHER says woof woof! I'm 5 years old! +``` + +As you can see, we create two dog objects using the `Dog` class. When initializing `dog_1`, the string `Jack` and the number `3` are passed, which sets the `name` and `age` attributes for that instance. And `dog_2` is initialized with the string `Thatcher` and number `5` as its `name` and `age`, respectively. + +Then when you call the `.bark()` method on `dog_1` and `dog_2`, you can see how both outputs differ, and use the unique `name` and `age` attributes you passed in when creating each object. + +In summary, the difference between a class and an object is that a class is the template or the blueprint, and an object is what is created using that template. + +Also, a class defines what data and behavior the object should have, and an object holds the actual data and uses that behavior. You write a class once, and you can make many objects from it, each with different data. + # --questions-- ## --text-- -Question 1 +What is the output of this code? + +```python +class Dog: + def __init__(self, name): + self.name = name + + def bark(self): + print(f"{self.name} says Woof!") + +my_dog = Dog("Rex") +print(my_dog.name) +``` ## --answers-- -Answer 1.1 +`Rex says Woof!` ### --feedback-- -Feedback 1 +Look at what is being printed: is it calling a method or accessing an attribute? --- -Answer 1.2 +`name` ### --feedback-- -Feedback 1 +Look at what is being printed: is it calling a method or accessing an attribute? --- -Answer 1.3 - -### --feedback-- - -Feedback 1 +`Rex` --- -Answer 1.4 +Error ### --feedback-- -Feedback 1 +Look at what is being printed: is it calling a method or accessing an attribute? ## --video-solution-- -5 +3 ## --text-- -Question 2 +What is the special method that gets automatically called when a new object is created? ## --answers-- -Answer 2.1 +`__create_object__` ### --feedback-- -Feedback 2 +Think about what initializes the attributes an object will have. --- -Answer 2.2 - -### --feedback-- - -Feedback 2 +`__init__` --- -Answer 2.3 +`__new__` ### --feedback-- -Feedback 2 +Think about what initializes the attributes an object will have. --- -Answer 2.4 +`__setup__` ### --feedback-- -Feedback 2 +Think about what initializes the attributes an object will have. ## --video-solution-- -5 +2 ## --text-- -Question 3 +What is the blueprint or template for creating objects? ## --answers-- -Answer 3.1 +A variable ### --feedback-- -Feedback 3 +Think about what defines the structure and behavior of objects created from it. --- -Answer 3.2 +A function ### --feedback-- -Feedback 3 +Think about what defines the structure and behavior of objects created from it. --- -Answer 3.3 - -### --feedback-- - -Feedback 3 +A class --- -Answer 3.4 +A loop ### --feedback-- -Feedback 3 +Think about what defines the structure and behavior of objects created from it. ## --video-solution-- -5 +3 diff --git a/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/6874b5fc38f90f25e18093ce.md b/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/6874b5fc38f90f25e18093ce.md new file mode 100644 index 00000000000..68b65b820cb --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/6874b5fc38f90f25e18093ce.md @@ -0,0 +1,209 @@ +--- +id: 6874b5fc38f90f25e18093ce +title: What Are Methods and Attributes, and How Do They Work? +challengeType: 19 +dashedName: what-are-methods-and-attributes-and-how-do-they-work +--- + +# --description-- + +In the last lecture, you learned about classes and how they act as blueprints for creating objects. + +Here, we will dive deeper into attributes and methods. + +Let's take a closer look at attributes first, then methods. + +Attributes are variables that belong to an object, so they hold data. There are two kinds of attributes: instance attributes and class attributes. + +Instance attributes are unique to each object created from a class, and you usually set them with the `__init__` method. Class attributes, on the other hand, belong to the class itself and are shared by all instances of that class. + +To access an attribute, you use dot notation. + +Here are examples of both instance and class attributes, and how to access them from objects: + +```python +class Dog: + species = "French Bulldog" # Class attribute + + def __init__(self, name): + self.name = name # Instance attribute + +print(Dog.species) # French Bulldog + +dog1 = Dog("Jack") +print(dog1.name) # Jack +print(dog1.species) # French Bulldog + +dog2 = Dog("Tom") +print(dog2.name) # Tom +print(dog2.species) # French Bulldog +``` + +Note that you can access class attributes directly from the class itself, but you need to create an object and pass it data first before you can access instance attributes. + +Cars are another good example, since all cars have a model and color: + +```python +class Car: + def __init__(self, color, model): + self.color = color + self.model = model + +car_1 = Car("red", "Toyota Corolla") +car_2 = Car("green", "Lamborghini Revuelto") + +print(car_1.model) # Toyota Corolla +print(car_2.model) # Lamborghini Revuelto + +print(car_1.color) # red +print(car_2.color) # green +``` + +Methods are functions defined inside a class. With them, any object defined from a class can perform actions that operate on or modify its own data. You also access a method with dot notation. + +For example, dogs can bark. So we can have a `bark` method in the `Dog` class like you saw in a previous lecture: + +```python +class Dog: + species = "French Bulldog" + + def __init__(self, name): + self.name = name + + def bark(self): + return f"{self.name} says woof woof!" + +jack = Dog("Jack") +jill = Dog("Jill") + +print(jack.bark()) # Jack says woof woof! +print(jill.bark()) # Jill says woof woof! +``` + +A `Car` class can also have a `describe` method: + +```python +class Car: + def __init__(self, color, model): + self.color = color # Instance attribute + self.model = model # Instance attribute + + def describe(self): + return f"This car is a {self.color} {self.model}" + +car_1 = Car("red", "Toyota Corolla") +car_2 = Car("green", "Lamborghini Revuelto") + +print(car_1.describe()) # This car is a red Toyota Corolla +print(car_2.describe()) # This car is a green Lamborghini Revuelto +``` + +# --questions-- + +## --text-- + +What are the two types of attributes in Python? + +## --answers-- + +Public and private attributes + +### --feedback-- + +Think about the two ways you can define attributes. + +--- + +Local and global attributes + +### --feedback-- + +Think about the two ways you can define attributes. + +--- + +Instance attributes and class attributes + +--- + +Mutable and immutable attributes + +### --feedback-- + +Think about the two ways you can define attributes. + +## --video-solution-- + +3 + +## --text-- + +What is required to access instance attributes? + +## --answers-- + +The class name only + +### --feedback-- + +Think about how you access class attributes versus how you access instance attributes. + +--- + +Decorators + +### --feedback-- + +Think about how you access class attributes versus how you access instance attributes. + +--- + +An instance or object of the class + +--- + +A static method + +### --feedback-- + +Think about how you access class attributes versus how you access instance attributes. + +## --video-solution-- + +3 + +## --text-- + +How do you define and access methods? + +## --answers-- + +As standalone functions outside a class, accessed with brackets + +### --feedback-- + +They belong to the class but operate on object data. + +--- + +As variables in a class, accessed like attributes + +### --feedback-- + +They belong to the class but operate on object data. + +--- + +With special keywords, called automatically + +### --feedback-- + +They belong to the class but operate on object data. + +--- + +They are defined inside a class and accessed with dot notation + +## --video-solution-- + +4 diff --git a/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/6874b7d3b286c538b39d0c25.md b/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/6874b7d3b286c538b39d0c25.md new file mode 100644 index 00000000000..892df9af129 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/lecture-classes-and-objects/6874b7d3b286c538b39d0c25.md @@ -0,0 +1,280 @@ +--- +id: 6874b7d3b286c538b39d0c25 +title: What Are Special Methods and What Are They Used For? +challengeType: 19 +dashedName: what-are-special-methods-and-what-are-they-used-for +--- + +# --description-- + +Special methods in Python, also known as "magic methods" or "dunder methods", are special Python methods that start and end with double underscores (`__`). The word "dunder" itself comes from double underscores (**d** for double, **under** for underscores). + +You've probably used special methods already without knowing it. Every time you write something like `3 + 4`, Python quietly runs `3.__add__(4)` under the hood. That's a special method in action. So while you *can* call special methods directly, you rarely do. Something like `3 + 4` is much clearer and easier to read than calling `3.__add__(4)` yourself. + +Apart from `__add__`, `__init__()` is another special method you'll see and use the most, as it's a class initializer. There are also others like `__len__()` and `__str__()`. + +Think of special methods as the directors of the activities between a person programming and the Python language interpreter itself. + +Remember, you don't need to call special methods directly. Instead, Python automatically calls them when certain actions happen. These operations include: + +- **Arithmetic operations like addition, subtraction, multiplication, division, and others**. In addition, `__add__()` is called, `__sub__()` for subtraction, `__mul__()` for multiplication, and `__truediv__()` for division. + +- **String operations like concatenation, repetition, formatting, and conversion to text**. `__add__()` is called for concatenation, `__mul__()` for repetition, `__format__()` for formatting, `__str__()` and `__repr__()` for text conversion, and so on. + +- **Comparison operations like equality, less-than, greater-than, and others**. `__eq__()` is called for equality checks, `__lt__()` for less-than, `__gt__()` for greater-than, and so on. + +- **Iteration operations like making an object iterable and advancing through items**. `__iter__()` is called to return an iterator and  `__next__()` to fetch the next item. + + +Normally, Python data types like strings and numbers already know how to add things, do concatenation, compare for equality, be used in loops, and others. + +But when you create your own class, Python won't know how to handle things automatically. + +This is where special methods come in — they let you customize Python's built-in behavior. + +Let's say you want to get the number of pages in book objects created with the class below, or compare them and get a readable string of the objects. Here's what happens without special methods: + +```python +class Book: + def __init__(self, title, pages): + self.title = title + self.pages = pages + +book1 = Book("Built Wealth Like a Boss", 420) +book2 = Book("Be Your Own Start", 420) + +print(len(book1)) # TypeError: object of type 'Book' has no len() +print(str(book1)) # <__main__.Book object at 0x102ed2900> +print(book1 == book2) # False even though they have the same number of pages +``` + +In the example: + +- `len(book1)` failed because Python doesn't know how to get the length of your book object without `__len__()` + +- `str(book1)` printed something like `<__main__.Book object at 0x102ed2900>` because that's the default representation when you don't use `__str__()` + +- `book1 == book2` resulted in `False` because Python just checks if both objects are the same in memory, not by content. + + +Here's how you can define your own `__len__()`, `__str__()`, and `__eq__()` special methods to make working with objects created from the `Book` class easier: + +```python +class Book: + def __init__(self, title, pages): + self.title = title + self.pages = pages + + def __len__(self): + return self.pages + + def __str__(self): + return f"'{self.title}' has {self.pages} pages" + + def __eq__(self, other): + return self.pages == other.pages + +book1 = Book("Built Wealth Like a Boss", 420) +book2 = Book("Be Your Own Start", 420) + +print(len(book1)) # 420 +print(len(book2)) # 420 +print(str(book1)) # 'Built Wealth Like a Boss' has 420 pages +print(str(book2)) # 'Be Your Own Start' has 420 pages +print(book1 == book2) # True +``` + +Another example is a shopping cart where you do the following: + +- Add items to the cart + +- Remove items from the cart + +- Get the number of items in the cart + +- Check what items are in the cart + +- Check if a specific item is in the cart + +- Return or display an item at a specific index in the cart + + +While you might have a method that adds items to the cart and removes certain items from the cart, you can create special methods for all the other functionality: + +- `__len__()` to get the length of the items in the cart + +- `__iter__()` to loop through the items in the cart so you can see them + +- `__contains__()` to check if a specific item is in the cart + +- `__getitem__()` to return or display an item at a specific index in the cart + + +Here's an example of a `Cart` class with these user-defined methods and special methods: + +```python +class Cart: + def __init__(self): + self.items = [] + + def add(self, item): + self.items.append(item) + + def remove(self, item): + if item in self.items: + self.items.remove(item) + else: + print(f'{item} is not in cart') + + def list_items(self): + return self.items + + def __len__(self): + return len(self.items) + + def __getitem__(self, index): + return self.items[index] + + def __contains__(self, item): + return item in self.items + + def __iter__(self): + return iter(self.items) +``` + +And here's how you can use them: + +```python +cart = Cart() +cart.add('Laptop') +cart.add('Wireless mouse') +cart.add('Ergo keyboard') +cart.add('Monitor') + +for item in cart: + print(item, end=' ') # Laptop Wireless mouse Ergo keyboard Monitor + +print(len(cart)) # 4 +print(cart[3]) # Monitor + +print('Monitor' in cart) # True +print('banana' in cart) # False + +cart.remove('Ergo keyboard') + +print(cart.list_items()) # ['Laptop', 'Wireless mouse', 'Monitor'] + +cart.remove('banana') # banana is not in cart +``` + +And those are a few ways you'll use special methods in Python in the real-world. + +# --questions-- + +## --text-- + +Which of these is the special method called during an addition operation? + +## --answers-- + +`__plus__()` + +### --feedback-- + +Look out for what is triggered when you use the `+` operator. + +--- + +`__sum__()` + +### --feedback-- + +Look out for what is triggered when you use the `+` operator. + +--- + +`__add__()` + +--- + +`__concat__()` + +### --feedback-- + +Look out for what is triggered when you use the `+` operator. + +## --video-solution-- + +3 + +## --text-- + +How was the word "dunder" derived? + +## --answers-- + +From "dynamic under-the-hood operations" + +### --feedback-- + +Think about how the word "dunder" is related to how dunder methods are written. + +--- + +From shortening "double underscore" (`__`) + +--- + +From the creator of Python's nickname + +### --feedback-- + +Think about how the word "dunder" is related to how dunder methods are written. + +--- + +From "data under" in reference to hidden methods + +### --feedback-- + +Think about how the word "dunder" is related to how dunder methods are written. + +## --video-solution-- + +2 + +## --text-- + +Which special method is called when you use the greater-than (`>`) comparison operator? + +## --answers-- + +`__more__()` + +### --feedback-- + +It stands for "greater than" and is triggered by the `>` operator. + +--- + +`__compare__()` + +### --feedback-- + +It stands for "greater than" and is triggered by the `>` operator. + +--- + +`__greater__()` + +### --feedback-- + +It stands for "greater than" and is triggered by the `>` operator. + +--- + +`__gt__()` + +## --video-solution-- + +4