cs61a spring 2018 Lab 6: Object-Oriented Programming 1
笔记摘录
Nonloacl
A variable is nonlocal to a frame if it is defined in the environment that the frame belongs to but not the frame itself, i.e. in its parent or ancestor frame.
for example:
def make_adder(x):
""" Returns a one-argument function that returns the result of
adding x and its argument. """
def adder(y):
return x + y
return adder
when we call make_adder, we create a function adder that is able to look up the name x in make_adder’s frame and use its value.
the different between the below function:
def make_counter():
"""Makes a counter function.
>>> counter = make_counter()
>>> counter()
1
>>> counter()
2
"""
count = 0
def counter():
count = count + 1
return count
return counter
There will be a UnboundLocalError. Because you try to compute count + 1 before the local variable was created! count is a local variable belongs to counter’s frame.
the nonlocal keyword. It allows us to update a variable in a parent frame!
def make_counter():
"""Makes a counter function.
>>> counter = make_counter()
>>> counter()
1
>>> counter()
2
"""
count = 0
def counter():
nonlocal count
count = count + 1
return count
return counter
The line nonlocal count tells Python that count will not be local to this frame, so it will look for it in parent frames. Now we can update count without running into problems.
Object-Oriented Programming
For a car class:
constructor
The constructor of a class is a function that creates an instance, or one single occurrence, of the object outlined by the class. Like this
def __init__(self, make, model):
self.make = make
self.model = model
self.color = 'No color yet. You need to paint me.'
self.wheels = Car.num_wheels
self.gas = Car.gas
make an instance of a class by using the name of the class.
>>> hilfingers_car = Car('Tesla', 'Model S')
attributes
class Car(object):
num_wheels = 4
gas = 30
headlights = 2
size = 'Tiny'
def __init__(self, make, model):
self.make = make
self.model = model
self.color = 'No color yet. You need to paint me.'
self.wheels = Car.num_wheels
self.gas = Car.gas
def paint(self, color):
self.color = color
return self.make + ' ' + self.model + ' is now ' + color
An instance attribute is a quality that is specific to an instance, and thus can only be accessed using dot notation (separating the instance and attribute with a period) on an instance. the make and model are two examples of instance attribute.
A class attribute is a quality that is shared among all instances of the class. For example, num_wheels, gas, headlights, size.
Think: Why the instance attribute gas is initialized to the value of Car.gas, the class attribute?
self.gas = Car.gas
Methods
Methods are functions that are specific to a class; only an instance of the class can use them.
dot notation to call methods on an instance
>>> hilfingers_car.paint('black')
'Tesla Model S is now black'
>>> hilfingers_car.color
'black'
You can also call methods using the class name and dot notation; for example,
>>> Car.paint(hilfingers_car, 'red')
'Tesla Model S is now red'
Think: The different between these two methods.
Inheritance
class MonsterTruck(Car):
size = 'Monster'
def rev(self):
print('Vroom! This Monster Truck is huge!')
def drive(self):
self.rev()
return Car.drive(self)
the class MonsterTruck is a subclass of the Car class. That means the MonsterTruck class inherits all the attributes and methods that were defined in Car, including its constructor!
add (or override) new attributes or methods that you want to be unique from those in the superclass. for example, the size.
>>> hilfingers_car.size
'Tiny'
>>> hilfingers_truck.size
'Monster'
Questions
Q1
class Car(object):
num_wheels = 4
gas = 30
headlights = 2
size = 'Tiny'
def __init__(self, make, model):
self.make = make
self.model = model
self.color = 'No color yet. You need to paint me.'
self.wheels = Car.num_wheels
self.gas = Car.gas
def paint(self, color):
self.color = color
return self.make + ' ' + self.model + ' is now ' + color
def drive(self):
if self.wheels < Car.num_wheels or self.gas <= 0:
return self.make + ' ' + self.model + ' cannot drive!'
self.gas -= 10
return self.make + ' ' + self.model + ' goes vroom!'
def pop_tire(self):
if self.wheels > 0:
self.wheels -= 1
def fill_gas(self):
self.gas += 20
return self.make + ' ' + self.model + ' gas level: ' + str(self.gas)
class MonsterTruck(Car):
size = 'Monster'
def rev(self):
print('Vroom! This Monster Truck is huge!')
def drive(self):
self.rev()
return Car.drive(self)
class Car(object):
num_wheels = 4
gas = 30
headlights = 2
size = 'Tiny'
def __init__(self, make, model):
self.make = make
self.model = model
self.color = 'No color yet. You need to paint me.'
self.wheels = Car.num_wheels
self.gas = Car.gas
def paint(self, color):
self.color = color
return self.make + ' ' + self.model + ' is now ' + color
def drive(self):
if self.wheels < Car.num_wheels or self.gas <= 0:
return self.make + ' ' + self.model + ' cannot drive!'
self.gas -= 10
return self.make + ' ' + self.model + ' goes vroom!'
def pop_tire(self):
if self.wheels > 0:
self.wheels -= 1
def fill_gas(self):
self.gas += 20
return self.make + ' ' + self.model + ' gas level: ' + str(self.gas)
class MonsterTruck(Car):
size = 'Monster'
def rev(self):
print('Vroom! This Monster Truck is huge!')
def drive(self):
self.rev()
return Car.drive(self)
hilfingers_car = Car('Tesla', 'Model S')
print(hilfingers_car.color)
print(hilfingers_car.paint('black'))
print( hilfingers_car.color)
hilfingers_truck = MonsterTruck('Monster Truck', 'XXL')
print(hilfingers_car.size)
print(hilfingers_truck.size)
print(hilfingers_car.drive())
print(hilfingers_car.drive())
print(hilfingers_car.gas)
print(Car.gas)
print(Car.headlights)
print(hilfingers_car.headlights)
Car.headlights = 3
print(hilfingers_car.headlights)
hilfingers_car.headlights = 2
print(Car.headlights)
hilfingers_car.wheels = 2
print(hilfingers_car.wheels)
print(Car.num_wheels)
print(hilfingers_car.drive())
# Car.drive() #TypeError: drive() missing 1 required positional argument: 'self'
print(Car.drive(hilfingers_car))
# print(MonsterTruck.drive(hilfingers_car)) #AttributeError: 'Car' object has no attribute 'rev'
class Car(object):
num_wheels = 4
gas = 30
headlights = 2
size = 'Tiny'
def __init__(self, make, model):
self.make = make
self.model = model
self.color = 'No color yet. You need to paint me.'
self.wheels = Car.num_wheels
self.gas = Car.gas
def paint(self, color):
self.color = color
return self.make + ' ' + self.model + ' is now ' + color
def drive(self):
if self.wheels < Car.num_wheels or self.gas <= 0:
return self.make + ' ' + self.model + ' cannot drive!'
self.gas -= 10
return self.make + ' ' + self.model + ' goes vroom!'
def pop_tire(self):
if self.wheels > 0:
self.wheels -= 1
def fill_gas(self):
self.gas += 20
return self.make + ' ' + self.model + ' gas level: ' + str(self.gas)
class MonsterTruck(Car):
size = 'Monster'
def rev(self):
print('Vroom! This Monster Truck is huge!')
def drive(self):
self.rev()
return Car.drive(self)
hilfingers_car = Car('Tesla', 'Model S')
deneros_car = MonsterTruck('Monster', 'Batmobile')
auto = deneros_car.drive()
print(auto)
print(Car.drive(deneros_car))
MonsterTruck.drive(deneros_car)
Car.rev(deneros_car) # AttributeError: type object 'Car' has no attribute 'rev'
class Car(object):
num_wheels = 4
gas = 30
headlights = 2
size = 'Tiny'
def __init__(self, make, model):
self.make = make
self.model = model
self.color = 'No color yet. You need to paint me.'
self.wheels = Car.num_wheels
self.gas = Car.gas
def paint(self, color):
self.color = color
return self.make + ' ' + self.model + ' is now ' + color
def drive(self):
if self.wheels < Car.num_wheels or self.gas <= 0:
return self.make + ' ' + self.model + ' cannot drive!'
self.gas -= 10
return self.make + ' ' + self.model + ' goes vroom!'
def pop_tire(self):
if self.wheels > 0:
self.wheels -= 1
def fill_gas(self):
self.gas += 20
return self.make + ' ' + self.model + ' gas level: ' + str(self.gas)
class MonsterTruck(Car):
size = 'Monster'
def rev(self):
print('Vroom! This Monster Truck is huge!')
def drive(self):
self.rev()
return Car.drive(self)
class FoodTruck(MonsterTruck):
delicious = 'meh'
def serve(self):
if FoodTruck.size == 'delicious':
print('Yum!')
if self.food != 'Tacos':
return 'But no tacos...'
else:
return 'Mmm!'
taco_truck = FoodTruck('Tacos', 'Truck')
taco_truck.food = 'Guacamole'
print(taco_truck.serve())
taco_truck.size = 'delicious'
print(taco_truck.serve())
# FoodTruck.pop_tire() # TypeError: pop_tire() missing 1 required positional argument: 'self'
FoodTruck.pop_tire(taco_truck)
taco_truck.drive()