6.1. Object-Oriented Python (215m) Flashcards
What Are Objects And Classes?
Sure! In programming, think of a “class” as a blueprint for making something. It’s like the concept of a “car” in general; you know a car has wheels, seats, and an engine, but this general idea doesn’t tell you anything about a specific car, like its color or make.
Objects are like individual instances or examples of that blueprint. If a “class” is the general concept of a “car,” then an “object” would be a specific car, like a red Toyota Corolla with a sunroof.
Classes and Objects in terms of Grammar:
- Class = Noun: A class is like a “noun,” a general concept that describes things. For example, “Dog” is a noun that represents a general concept of a four-legged animal that barks.
- Object = Proper Noun: An object is like a “proper noun,” a specific instance of that general concept. For example, “Fido” would be a specific dog with its own unique traits and behaviors.
- Attributes = Adjectives: Attributes are qualities or characteristics of the object. Just like adjectives describe nouns, attributes describe or provide more details about objects. For example, the color of the car, or the breed of the dog.
- Methods = Verbs: Methods are actions that the object can perform. Like how verbs show what a noun can do, methods define what an object can do. For example, a dog can “bark,” or a car can “accelerate.”
Example:
Let’s take a class called “Dog.”
- Class (Noun): Dog
- Attributes (Adjectives): Breed, Color, Age
- Methods (Verbs): Bark, Fetch
Now, let’s create an object from this class.
-
Object (Proper Noun): Fido
- Attributes (Adjectives): Golden Retriever, Yellow, 3 years
- Methods (Verbs): Fido can Bark, Fido can Fetch
So, a class is like the blueprint that tells us what a ‘Dog’ should have and be able to do, while an object is a specific ‘Dog’ with its own attributes and behaviors.
Treehouse Notes:
The class keyword lets us define a class. We use it just like we do the def keyword for making functions. Class definitions are blocks like function definitions.
class NewClass:
Inside of the class, variables are called attributes.
class NewClass: name_attribute = "Kenneth"
And functions that are defined inside of a class are called methods.
~~~
class NewClass:
name_attribute = “Kenneth”
def name_method(self): return self.name_attribute ~~~ Whenever we call a class, it creates an instance. Each instance has full access to the all of the attributes and methods of the class. ~~~ new_instance = NewClass() new_instance.name_method() ~~~
A method is a function defined inside of what?
A method is a function that is defined inside of a class. Unlike standalone functions, methods are designed to operate on instances of the class, often modifying the state or attributes of those instances.
In the context of our previous example with dogs, the methods like “Bark” and “Fetch” would be functions defined inside the “Dog” class. These methods would typically operate on specific instances (objects) of that class, like “Fido” or “Spot.”
Here’s a simplified Python example to illustrate:
```python
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
# Method (Verb) def bark(self): print(f"{self.name} says Woof!")
Create an Object (Proper Noun)
fido = Dog(name=”Fido”, breed=”Golden Retriever”)
Call a Method (Verb) on the Object
fido.bark() # Output: “Fido says Woof!”
~~~
In this example, bark
is a method defined inside the Dog
class. The fido
object is an instance of the Dog
class, and we can call the bark
method on this object.
In Python, only dictionaries, lists, tuples, and sets are objects. Is this true?
No, that statement is not true. In Python, nearly everything is an object. This includes not just dictionaries, lists, tuples, and sets, but also numbers, strings, functions, and even modules and classes themselves. Python is an object-oriented language, which means that it uses objects as a fundamental building block for constructing programs.
Examples:
-
Numbers are objects: You can find out the type of an object using the
type()
function.
python x = 42 print(type(x)) # Output: <class 'int'>
-
Strings are objects: They have methods like
upper()
,lower()
, etc.
python s = "hello" print(s.upper()) # Output: "HELLO"
-
Functions are objects: You can assign them to variables, pass them as arguments, etc.
```python
def my_function():
print(“Hello from my_function”)func_var = my_function
func_var() # Output: “Hello from my_function”
``` -
Modules are objects: You can assign them to variables and manage them just like any other object.
python import math print(type(math)) # Output: <class 'module'>
-
Even Classes are objects: They are instances of a meta-class.
```python
class MyClass:
passprint(type(MyClass)) # Output: <class ‘type’>
```
So, in Python, the concept of an “object” is very broad and not limited to just a few data types.
Sequence 1: The file characters.py contains:
~~~
class Thief:
pass
~~~
The following is run within terminal/console:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth
~~~
Sequence 2:
The file characters.py contains:
~~~
class Thief:
sneaky = True #attribute
~~~
The following is run within terminal/console:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.sneaky
~~~
Explain the sequence 1 and 2, what’s happening in it?
Certainly! Let’s go through both sequences step-by-step.
Sequence 1:
-
File Creation: The file
characters.py
contains a class definition forThief
. Thepass
statement is a placeholder indicating that the class is currently empty; it doesn’t have any attributes or methods yet.python class Thief: pass
-
Console/Terminal Steps:
-
python
: This command starts the Python interpreter. -
from characters import Thief
: This imports theThief
class from thecharacters.py
file. Now you can create instances (objects) of this class. -
kenneth = Thief()
: This creates a new object of theThief
class and assigns it to the variablekenneth
. -
kenneth
: This would display a representation of thekenneth
object, something like<\_\_main\_\_.Thief object at 0x7f8f9c0>
.
-
Sequence 2:
-
File Creation: The file
characters.py
has been updated to include an attributesneaky
in theThief
class, set toTrue
.python class Thief: sneaky = True # attribute
-
Console/Terminal Steps:
-
python
: Starts the Python interpreter. -
from characters import Thief
: Imports the updatedThief
class from thecharacters.py
file. -
kenneth = Thief()
: Creates a new object of theThief
class and assigns it to the variablekenneth
. -
kenneth.sneaky
: Accesses thesneaky
attribute of thekenneth
object. Sincesneaky
is set toTrue
in the class definition, this would returnTrue
.
-
Summary:
- In Sequence 1, you created an empty
Thief
class and made an instance of it. The instance didn’t have any special attributes or methods because the class was empty. - In Sequence 2, you added a
sneaky
attribute to theThief
class and set it toTrue
. When you made an instance of this updated class, you could access this attribute, which returnedTrue
.
In both sequences, the steps in the terminal are to import the class and create an instance (object) of that class. The key difference is in the attributes that the class and its instances have.
Challenge Task 1 of 2
Alright, it’s time create your first class all on your own! Make a new class
named Student
. Give it an attribute name
and put your own name, as a string, into the attribute.
Challenge Task 2 of 2
Now, create a variable named me
and assign it an instance of Student()
. Then print()
out the name
attribute of your instance.
Task 1:
~~~
class Student:
name = “Sethu”
~~~
Task 2:
~~~
class Student:
name = “Sethu”
me = Student()
print(me.name)
~~~
Sequence 1:
The file characters.py contains the following code:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
return bool(random.randint(0, 1))
~~~
The following code is run in console/terminal:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.pickpocket() #returns false
Thief.pickpocket() #returns error as has no self
Thief.pickpocket(kenneth) #kenneth is self, returns false
~~~
Sequence 2:
The file characters.py contains the following code:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
print(“Called by {}”.format(self))
return bool(random.randint(0, 1))
~~~
The following code is run in console/terminal:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.pickpocket()
Thief.pickpocket(kenneth)
~~~
Sequence 3:
The file characters.py contains the following code:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
if self.sneaky:
return bool(random.randint(0, 1))
return False
~~~
The following code is run in console/terminal:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.pickpocket() #returns True
kenneth.pickpocket() #returns Talse
kenneth.pickpocket() #returns True
kenneth.sneaky = False
kenneth.pickpocket() #returns False
kenneth.pickpocket() #returns False
kenneth.pickpocket() #returns False
~~~
Explain the sequence 1,2,3 and what’s happening in it?
Absolutely! Let’s break down what’s happening in each of the sequences.
Sequence 1:
-
File Code: In
characters.py
, aThief
class is defined with an attributesneaky
set toTrue
and a methodpickpocket
that returns a random boolean value (True
orFalse
).```python
import randomclass Thief:
sneaky = True
def pickpocket(self):
return bool(random.randint(0, 1))
``` -
Console Steps:
-
kenneth = Thief()
: Creates an objectkenneth
of classThief
. -
kenneth.pickpocket()
: Calls thepickpocket
method on thekenneth
object. This returnsFalse
due to the random number generated. -
Thief.pickpocket()
: Tries to callpickpocket
directly on the class, which results in an error because noself
argument is provided. -
Thief.pickpocket(kenneth)
: Callspickpocket
on the class, passingkenneth
as theself
argument. This works and returnsFalse
(due to random generation).
-
Sequence 2:
-
File Code: Similar to Sequence 1, but the
pickpocket
method now includes aprint
statement to show which object called it.python def pickpocket(self): print("Called by {}".format(self)) return bool(random.randint(0, 1))
-
Console Steps:
-
kenneth.pickpocket()
: Calls the method and prints “Called by <Thief>".</Thief> -
Thief.pickpocket(kenneth)
: Similar to the above but called directly on the class. It also prints the same message.
-
Sequence 3:
-
File Code: The
pickpocket
method now includes anif
condition that checks thesneaky
attribute before returning a random boolean.python def pickpocket(self): if self.sneaky: return bool(random.randint(0, 1)) return False
-
Console Steps:
-
kenneth.pickpocket()
: Called multiple times and returns eitherTrue
orFalse
based on random generation, becausesneaky
isTrue
. -
kenneth.sneaky = False
: Setssneaky
toFalse
. -
kenneth.pickpocket()
: Now always returnsFalse
assneaky
is set toFalse
.
-
Summary:
- Sequence 1: Demonstrates basic class and method usage, including how to call methods both on an instance and directly on the class.
- Sequence 2: Adds a print statement to show which instance is calling the method.
- Sequence 3: Adds conditional logic to the method based on an attribute, demonstrating how methods can access and use the attributes of the instance on which they are called. It also shows how changing an attribute affects the behavior of methods.
Challenge Task 1 of 1
This class should look familiar! First, I need you to add a method named praise
to the Student
class. It should take the self
argument. Then, inside the praise
method, return
a positive message about the student using the name
attribute. As an example, it could say “You’re doing a great job, Jacinta!” or “I really like your hair today, Michael!”. Feel free to change the name
attribute to your own name, too!
File: first_class.py:
~~~
class Student:
name = “Your Name”
~~~
Task 1:
Variant 1:
~~~
class Student:
name = “Sethu”
def praise(self): return "You're doing a great job {}".format(self.name) ~~~
Variant 2:
~~~
class Student:
name = “Sethu”
def praise(self): return f"You're doing a great job, {self.name}!" ~~~
Run:
~~~
# Adding a method named ‘praise’ to the Student class
class Student:
name = “Your Name”
def praise(self): return f"You're doing a great job, {self.name}!"
Create an instance of the Student class to test the praise method
student_instance = Student()
praise_message = student_instance.praise()
praise_message
~~~
Result:
~~~
“You’re doing a great job, Your Name!”
~~~
Sequence 1:
The file characters.py contains the following:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
if self.sneaky:
return bool(random.randint(0, 1))
return False
def hide(self, light_level):
return self.sneaky and light_level <10
~~~
The following code is run in Terminal/Console:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.hide(4)
kenneth.hide(14)
kenneth.sneaky = False
kenneth.hide(0)
~~~
Sequence 2:
The file characters.py contains the following:
~~~
import random
class Thief:
sneaky = True # attribute
def __init__(self, name, sneaky=True, **kwargs):
self.name = name
self.sneaky = sneaky
def pickpocket(self): # methods
return self.sneaky and bool(random.randint(0, 1))
def hide(self, light_level):
return self.sneaky and light_level < 10
~~~
The following code is run in Terminal/Console:
~~~
from characters import Thief
kenneth = Thief(“Kenneth”, False)
kenneth.name
kenneth.sneaky
~~~
Sequence 3:
The file characters.py contains the following:
~~~
import random
class Thief:
sneaky = True # attribute
def __init__(self, name, sneaky=True, **kwargs):
self.name = name
self.sneaky = sneaky
for key, value in kwargs.items(): setattr(self, key, value)
def pickpocket(self): # methods
return self.sneaky and bool(random.randint(0, 1))
def hide(self, light_level):
return self.sneaky and light_level < 10
~~~
The following code is run in Terminal/Console:
~~~
from characters import Thief
kenneth = Thief(“Kenneth”, scars=None, favorite_weapon=”Wit”)
kenneth.name
kenneth.sneaky
kenneth.favorite weapon
~~~
Explain the sequence 1,2,3 and what’s happening in it?
Certainly, let’s explore each sequence in more detail, taking into account both the code within characters.py
and the code run in the terminal.
Sequence 1
characters.py
- Thief
class is defined with a class attribute sneaky
set to True
.
- Two methods, pickpocket()
and hide(light_level)
, are also defined. pickpocket()
returns a random boolean if sneaky
is True
, and hide()
returns True
if sneaky
is True
and light_level
is less than 10.
Terminal/Console
- An object named kenneth
is created from the Thief
class.
- kenneth.hide(4)
is called and would return True
because light_level
(4) is less than 10 and sneaky
is True
.
- kenneth.hide(14)
would return False
because light_level
(14) is not less than 10.
- kenneth.sneaky
is set to False
.
- kenneth.hide(0)
is called and would now return False
because sneaky
is False
, irrespective of light_level
.
Sequence 2
characters.py
- Thief
class now includes an \_\_init\_\_
method to initialize name
and sneaky
attributes when a new object is created.
- pickpocket()
is modified to return a boolean based on both sneaky
and a random value between 0 and 1.
Terminal/Console
- A new object named kenneth
is created with sneaky
set to False
and name
set to “Kenneth”.
- Accessing kenneth.name
would return “Kenneth”.
- Accessing kenneth.sneaky
would return False
.
Sequence 3
characters.py
- Thief
class is further modified to accept arbitrary keyword arguments (**kwargs
) in the \_\_init\_\_
method.
- These keyword arguments are set as attributes on the object using the setattr
function.
Terminal/Console
- A new object named kenneth
is created with additional attributes: scars
is set to None
, and favorite_weapon
is set to “Wit”.
- Accessing kenneth.name
would return “Kenneth”.
- Accessing kenneth.sneaky
would return True
(default value as no value for sneaky
was provided during object creation).
- Accessing kenneth.favorite_weapon
would return “Wit”. Note: The code has a typo and uses kenneth.favorite weapon
which would actually result in a syntax error. It should be kenneth.favorite_weapon
.
In summary, these sequences display the evolution of the Thief
class, starting from a simple version to a more complex one that allows for custom attributes and initialization. The terminal/console interactions help to show how these class features can be accessed and modified for individual objects.
Challenge Task 1 of 1
Alright, I need you to make a new method named feedback
. It should take self
and an argument named grade
. Methods take arguments just like functions do.
Inside the feedback
method, if grade
is above 50, return the result of the praise
method. If it’s 50 or below, return the reassurance
method’s result.
first_class.py:
~~~
class Student:
name = “Your Name”
def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) ~~~
Task 1:
Certainly! To implement the feedback
method, you can check the value of the grade
argument and return the result of either the praise
or reassurance
method accordingly. Here’s how you can update the Student
class in first_class.py
:
```python
class Student:
name = “Your Name”
def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() else: return self.reassurance() ~~~
Now, the Student
class has a feedback
method that takes a grade
argument. If grade
is greater than 50, the method returns the result of praise()
. Otherwise, it returns the result of reassurance()
.
You can test the feedback
method by creating an instance of the Student
class and calling it:
```python
student1 = Student()
student1.name = “Alice”
print(student1.feedback(60)) # Output: “You inspire me, Alice”
print(student1.feedback(40)) # Output: “Chin up, Alice. You’ll get it next time!”
~~~
Challenge Task 1 of 2:
Our Student
class is coming along nicely!
I’d like to be able to set the name
attribute at the same time that I create an instance. Can you add the code for doing that?
Override the \_\_init\_\_
method by adding your own \_\_init\_\_
method to the Student class. Add self and name as arguments to the \_\_init\_\_
method. Inside of \_\_init\_\_
, set self.name
to the argument name
.
first_class.py:
~~~
class Student:
name = “Your Name”
def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~
Challenge Task 2 of 2:
Sometimes I have other attributes I need to store on a Student
instance. Add **kwargs
as an argument to the \_\_init\_\_
method. Then use setattr
inside the \_\_init\_\_
method to add attributes for any other key/value pairs I want to send to the instance when I create it.
first_class.py:
~~~
class Student:
name = “Your Name”
def \_\_init\_\_(self, name): self.name = name def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~
Task 1:
~~~
class Student:
name = “Your Name”
def \_\_init\_\_(self, name): self.name = name def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~
Task 2:
~~~
class Student:
name = “Your Name”
def \_\_init\_\_(self, name, **kwargs): self.name = name for key, value in kwargs.items(): setattr(self, key, value) def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~