Object-Oriented Programming
- OOP provides a method for organizing large programs
- large programs can be organized into small, modular components that can be developed at ones.
- Extends data abstraction, but also combines information and behavior.
- Objects represent their real-life counterparts (or they can be an abstract idea!)
- This allows our code to not just be a long list of instructions, but rather the combined interactions of many small objects and components.
- Each object has its own local state, which may change over time.
- Mutation happens at a local state, not at a global level.
- Mutations only occur to a certain object, and each object should know how to manage its local state.
- Interactions with an object occur through the methods.
- Objects are all instances of a common class.
- The class provides a blueprint for constructing the objects.
- Different classes relate to each other
- Specialized language and vocab:
- Class: Defines how objects of a type behave.
- Object: An instance of a class, with it’s type the class.
- Method: A function called on an object using dot expression (
<object>.<method>()
)- Functions are typically defined within the global frame, but a method is specific to a particular object.
- Ex: Python lists are an example of a class
1
list
1
list
- In fact, just calling list by itself is just referencing the constructor of the class, creating a new instance of a list.
1
2
s = list(range(3))
print("type(s):", type(s),"\nand s:", s)
1
2
type(s): <class 'list'>
and s: [0, 1, 2]
- All list operations, from methods (append, extend, sort, insert, pop, remove), to arithmetic operations, to item lookup and assignment, are implemented/defined within the list class.
Classes
- Class describes the behavior of its instances
- Ex: All bank accounts have a balance and an account holder; the Account class should add those attributes to each newly created instance.
- The class is a blueprint for creating objects/instances of that class.
- Every class has attributes and methods.
- Attributes are like variables, they store information.
- Methods are like functions, they perform operations to the Object.
- We access attributes and methods using the dot notation.
- Different objects share common behavior and attributes as they are instances of the same class.
- Every bank account has a balance and acount holder. Additionally, every account can also deposit and withdraw money.
- Everything within an object is defined locally to that object. We may not access it without specifying the object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Account:
company = "CS61A Bank" # This is a class variable
def __init__(self, account_holder):
self.balance = 0 # This is an instance variable
self.holder = account_holder
def deposit(self, ammount): # This is an instance method
self.balance = self.balance + ammount
return self.balance
def withdraw(self, amount):
if amount > self.balance:
return "Insufficient funds"
self.balance = self.balance - amount
return self.balance
def foo(x): # This is a class method
return Account.company
def transfer(self, into, amount):
result = self.withdraw(amount)
if type(result) == str:
return result
else:
into.deposit(amount)
return "Transfer Successful"
a = Account("Alex")
a.deposit(50000)
b = Account("Bobby")
b.deposit(10000)
a.transfer(b, 20000)
print(a.balance) # 30000
print(b.balance) # 30000
1
2
30000
30000
- The
__init__()
method is a special method name that functions as a constructor for the class- It defines the behavior of the class whenever a new object instance is created (what values to store, calculations to make, algorithms to run, etc.)
- The keyword
self
is used to refer to the instance of the class itself.
Creating Instances
- Object Construction
- A new instances of the class is created, it is a blank slate. This blank slate has no attributes.
- The
__init__
method of the class is called with the new object as its first argument (namedself
), along with any additional arguments provided in the call expression- Think of the
self
argument as being the name of the object that we are calling
- Think of the
Instance Attributes
- An object’s attributes are accessed and mofieid using dot expressions:
1 2 3 4 5 6
>>> a = Account('Alan') >>> a.balance 0 >>> a.balance = 12 >>> a.balance 12
- An attribute may be asigned any value, even if that attribute did not exist before.
1
2
3
4
5
6
a = Account('Alan')
a.balance = 20
b = Account("Bobby")
b.balance = 20
a.backup = b # This is an attribute that is bound to another object! This attribute also did not exist in the class definition
a.backup.balance
1
20
Object Identity
- Important as object attributes may change.
- Identity may help us with identifying if two objects with the same attributes are indeed the same object, or if they are different.
- Every object instance of a class has a unique identity
- We may test if two expressoins evaluate to the same Object by using the Identity operators
is
andis not
1
2
3
4
a = Account('John')
b = Account('Jack')
print("Is a the same as a?", a is a)
print("Is a the same as b?", a is b)
1
2
Is a the same as a? True
Is a the same as b? False
- However, when we bind an object to a new name with assignment, we do not create a new object. There is simply just an additional name that references the same object.
1
2
c = a
c is a
1
True
Methods
- To invoke methods, we use the dot expression.
- All invoked methods have access to the object because of the
self
parameter. - Because of this, the method is capable of accessing and manipulating the attributes of the object.
- All invoked methods have access to the object because of the
- The dot notation automatically supplies the first argument to the method.
- We create unique methods for each class because different types might have different behaviors for each action
- Ex: The deposit actions of a bank differs than that of the deposit actions of a hedge fund.