1 创建类
使用类可以模拟任何东西
以9.1.1 创建dog类
为例子,表示的不是特定的小狗,是所有小狗。
- 9.1.1 创建dog类
class Dog():
"""A simple attempt to model a dog.一次模拟小狗的简单尝试"""
def __init__(self, name, age):
"""Initialize name and age attributes.初始化属性name和age"""
self.name = name
self.age = age
def sit(self):
"""Simulate a dog sitting in response to a command.模拟小狗被命令时蹲下"""
print(self.name.title() + " is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command.模拟小狗被命令时打滚"""
print(self.name.title() + " rolled over!")
将上面的代码拆分成两个部分,首先是基本信息,它们具备两项信息(名字和年龄)
def __init__(self, name, age):
"""Initialize name and age attributes.初始化属性name和age"""
self.name = name
self.age = age
接着是行为(蹲下和打滚)
def sit(self):
"""Simulate a dog sitting in response to a command.模拟小狗被命令时蹲下"""
print(self.name.title() + " is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command.模拟小狗被命令时打滚"""
print(self.name.title() + " rolled over!")
两串代码可以得到:根据Dog
类创造的每个实例都会存储名字和年龄,以及蹲下和打滚两种能力。
- 关于 方法
__init__()
将方法__init__()
拆成方法和__init__()
来讲解
2.1 关于方法
类中的函数称为方法,函数的一切适用于方法
唯一差别是在于调用方法的方式,调用方法的方式我的理解就是方法是采用句点表示法,见后面。
2.2 关于__init__()
它是一个特殊的方法
第一点,根据XX类创建实例的时候,例如根据Dog
类创建实例的时候my_dog = Dog(XXXX)
,会自动运行__init__()
。
第二点,开头和结尾各有__
是为了和普通方法区别
2.3 以9.1.1 创建dog类
作为例子讲解__init__()
在9.1.1 创建dog类
中,它有三个形参,分别是self
、name
和age
。self
必不可少,并且在其他参数的前面。
Python调用__init__()
创建Dog
类实例的时候,会自动传入实参self
。注意区别实参和形参(在第8章 函数有提及:形参是函数完成其工作所需的一项信息,实参是调用函数时传递给函数的信息)
每个与类相关联的方法调用会自动传递实参self
,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
创造Dog
类实例的时候,Python调用Dog
类的方法__init__()
,通过实参向Dog()
传递名字和年龄,self
会自动传递,因此我们不需要传递,只需要给两个形参提供值。
- 我自己的理解:
(1) **创造实例my_dog
的时候,编程输入my_dog=Dog('willie', 6)
之后Python
内部调用__init__()
创建Dog
类的实例,自动传入实参self
,my_dog
就是self
,my_dog
会保存输入的两个参数(名字和年龄)
(2)接着当调用与类相关联的方法的时候,会自动传递实参self
(3)__init__()
是一个指向实例本身的应用,可以访问类中的属性和方法
(4) 最后我们可以发现在9.1.1 创建dog类
代码块中,两个变量name
和age
都有前缀self
,也就是下面这几行代码
class Dog():
"""A simple attempt to model a dog.一次模拟小狗的简单尝试"""
def __init__(self, name, age):
"""Initialize name and age attributes.初始化属性name和age"""
self.name = name
self.age = age
name
和age
是在创造实例的时候就输入,例如代码my_dog = Dog('willie', 6)
,根据代码含义这个时候就是把实参willie
和6
实参存储到形参name
和age
上,
然后Python调用__init__()
使用self.name = name
和self.age = age
获得存储在形参name
和age
的值,然后存储到变量name
和age
上,接着变量被关联到当前创建的实例。
自己认为的逻辑是先创造实例my_dog = Dog('willie', 6)
,其中实参willie
和6
会因为__init__(self,name,age)
存储到形参name
和age
上,接着根据代码
self.name = name
self.age = age
存储到self.name
和self.age
上,在P139中写到以self为前缀的变量都可供类中的所有方法使用,还可以通过类的任何实例来访问这些变量
- 补充说明
(1)根据约定,在Python中,首字母大写的名称是类。
(2)9.1.1 创建dog类
的定义中的类的括号是空的,因为我们要从空白中去创造这个类,后面还有一个父类和子类的概念,那个时候就不是空白的了。
2 使用类
- 9.1.2 根据类创造实例
class Dog():
"""A simple attempt to model a dog.一次模拟小狗的简单尝试"""
def __init__(self, name, age):
"""Initialize name and age attributes.初始化属性name和age"""
self.name = name
self.age = age
def sit(self):
"""Simulate a dog sitting in response to a command.模拟小狗被命令时蹲下"""
print(self.name.title() + " is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command.模拟小狗被命令时打滚"""
print(self.name.title() + " rolled over!")
my_dog = Dog('willie', 6)
# 上面的这些是实例,直接运行是没有print的
# python使用实参'willie'和6调用Dog类的方法_init_()。
# 方法_init_()创建一个表示特定小狗的示例,并使用我们提供的值来设置属性name和age
# _init_()没有显式地包含return语句,但是python自动返回一个表示这条小狗的示例
'访问属性'
print("My dog's name is " + my_dog.name.title() + ".")
# My dog's name is Willie.
# 把属性name的值“willie”改成首字母大写的
print("My dog is " + str(my_dog.age) + " years old.")
# My dog is 6 years old.
# 把属性age的值6转换为字符串
'调用方法'
my_dog.sit()
# Willie is now sitting.
my_dog.roll_over()
# Willie rolled over!
'创建多个实例'
your_dog = Dog('lucy', 3)
print("\nMy dog's name is " + your_dog.name.title() + ".")
# My dog's name is Lucy.
print("My dog is " + str(your_dog.age) + " years old.")
# My dog is 3 years old.
your_dog.sit()
# Lucy is now sitting.
- 对上面
9.1.2 根据类创造实例
进行小结:
(1)一开始我的理解是创造类后(包括属性和方法),然后根据类创造实例my_dog = Dog('willie', 6)
,因为之前说过“会自动传递实参self
”,我以为会自动运行,把sit
和roll_over
运行,但是没有。随后仔细看发现是当调用与类相关联的方法的时候,会自动传递实参self
,我一开始只是创造实例但是并没有调用与类相关的方法。
(2)关于调用类的方法和属性,前面提及到“ __init__()
是一个指向实例本身的应用,可以访问类中的属性和方法”。
(3)源于P140:Python使用实参wille
和6
调用Dog
类中的方法__init__()
。方法__init__()
创造一个表示特定小狗的特例,并且使用我们所给的值设置属性name
和age
。方法__init__()没有显性地包含return
语句,但是python会自动返回一个表示这条小狗的实例,这个实例会存储在变量my_dog
中。
(4)一般首字母大写的是类,小写的是根据类创造的实例。
(5)访问实例的属性和方法,用句号表示法
例如
my_dog.name
my_dog.sit()
访问属性的操作看起来就像是先找到实例my_dog
,然后再查找和这个实例相关的name
。要注意,在Dog
类中引用这个属性的时候,使用的是self.name
。调用方法也是类似,指定实例的名称和调用的方法,并用句点分割它们。此处就是Python在类Dog
中查找方法sit()
并运行其代码。
句号表示法优点在于如果给属性和方法制定了合适的描述性名称,哪怕是从来没有见过的代码块,也可以推断它是什么作用。
(6)根据类创造任意数量的实例,条件是将每个实例都存储在不同的变量中,或占用列表或字典不同地方。
(7)调用一些方法不一定会输出print
,还要看里面怎么写,如果是return
就没有结果
3 使用类和实例
- 9.2.1 car类
之前是以狗为例子,现在以车为例子
这一章节主要是和属性有关。
"""A class that can be used to represent a car."""
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""初始化描述汽车的属性 Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
my_new_car = Car("audi","a4",2016)
my_new_car.get_descriptive_name()
# 什么也没有print,是因为用了return
print(my_new_car.get_descriptive_name())
# 2016 Audi A4
- 9.2.2 给属性指定默认值
"""A class that can be used to represent a car."""
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""初始化描述汽车的属性 Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
my_new_car = Car("audi","a4",2016)
print(my_new_car.get_descriptive_name())
# 2016 Audi A4
my_new_car.read_odometer()
# This car has 0 miles on it.
# 前者要用print,后者不用。因为在设定方法的时候前者用了return,后者是print
- 9.2.3 修改属性的值(直接修改)
'直接修改属性的值'
"""A class that can be used to represent a car."""
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""初始化描述汽车的属性 Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
my_new_car = Car("audi","a4",2016)
print(my_new_car.get_descriptive_name())
# 2016 Audi A4
my_new_car.read_odometer()
# This car has 0 miles on it.
# 前者要用print,后者不用。因为在设定方法的时候前者用了return,后者是print
my_new_car.odometer_reading = 23
# my_new_car.read_odometer = 23 这里我一开始用的是这个
# 但是这是函数,如果算下去是错的,'int' object is not callable
my_new_car.read_odometer()
# This car has 23 miles on it.
- 9.2.3 修改属性的值(通过方法)
'通过修改属性的值'
"""A class that can be used to represent a car."""
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""初始化描述汽车的属性 Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
self.odometer_reading = mileage
my_new_car = Car("audi","a4",2016)
print(my_new_car.get_descriptive_name())
# 2016 Audi A4
my_new_car.update_odometer(23)
my_new_car.read_odometer()
# This car has 23 miles on it.
- 9.2.3 修改属性的值(通过方法,禁止回调)
'通过方法修改属性的值'
"""A class that can be used to represent a car."""
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""初始化描述汽车的属性 Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
my_new_car = Car("audi","a4",2016)
print(my_new_car.get_descriptive_name())
# 2016 Audi A4
my_new_car.update_odometer(23)
my_new_car.read_odometer()
# This car has 23 miles on it.
my_new_car.update_odometer(10)
my_new_car.read_odometer()
# You can't roll back an odometer!
# This car has 23 miles on it.
# 这里禁止回调了,但是数值23还在,read_odometer函数也还是调用了
- 9.2.3 通过方法对属性的值进行递增
'通过方法修改属性的值'
"""A class that can be used to represent a car."""
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""初始化描述汽车的属性 Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""将里程碑度数增加指定的量Add the given amount to the odometer reading."""
self.odometer_reading += miles
my_used_car=Car("subaru","outback",2013)
print(my_used_car.get_descriptive_name())
# 2013 Subaru Outback
my_used_car.update_odometer(245)
my_used_car.read_odometer()
# This car has 245 miles on it.
my_used_car.increment_odometer(200)
my_used_car.read_odometer()
# This car has 445 miles on it.
对上面(从9.2.1 car类
到9.2.3 通过方法对属性的值进行递增
)关于属性部分进行小结:
(1)类中的每个属性必须要有初始值,哪怕是0还是空字符串。
比如设置默认值,在方法__init__()指定默认值也是可以的,比如9.2.2 给属性指定默认值
def update_odometer(self,mileage):
self.odometer_reading = mileage
要注意,这里不像之前一样只有self
了,而且还多了一个参数,一个我们想要去修改的参数odometer_reading
,更新后再存储
此外我们还可以加入限制条件,例如9.2.3 修改属性的值(通过方法,禁止回调)
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
"""初始化描述汽车的属性 Initialize attributes to describe a car."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
其中的self.odometer_reading = 0
就是默认参数。
此外如果对某个属性进行了这种操作,就无需提供初始值的形参了,比如my_new_car = Car("audi","a4",2016)
(2)接下来是关于属性的修改,分为三种方式:直接通过实例进行修改,通过方法进行设置,通过方法进行递增。
但是个人觉得第二种和第三种是一样的,其实都是方法。
首先说第一点,直接通过实例进行修改
例如代码9.2.3 修改属性的值(直接修改)
其中的
my_new_car.update_odometer(23)
就是在指定默认值后再次修改,是使用了句号表示法直接访问并设置汽车的属性odometer_reading
,也就是Python在实例my_new_car
中找到属性odometer_reading
,然后把该属性值设置为23
第二点是关于方法的修改,如果设置了更新属性的方法,就不用直接访问属性,可以将值传递给一个方法,让它在内部进行更新。
比如9.2.3 修改属性的值(通过方法)
其中的my_new_car.update_odometer(23)
class Car():
"""一次模拟汽车的简单尝试 A simple attempt to represent a car."""
def __init__(self, make, model, year):
跳过
def get_descriptive_name(self):
跳过
def read_odometer(self):
跳过
def update_odometer(self,mileage):
self.odometer_reading = mileage
my_new_car = Car("audi","a4",2016)
print(my_new_car.get_descriptive_name())
# 2016 Audi A4
my_new_car.update_odometer(23)
my_new_car.read_odometer()
# This car has 23 miles on it.
对于属性的直接修改和用方法修改分别是:
前者是 self.odometer_reading = 0
然后my_new_car.odometer_reading = 23
再调用my_new_car.read_odometer()
而后者是方法update_odometer()
def update_odometer(self,mileage):
self.odometer_reading = mileage
然后再update_odometer(23)
再read_odometer()
my_new_car.update_odometer(23)
my_new_car.read_odometer()
先用方法update_odometer(23)
更新(这里是有输入参数23的),再调用方法read_odometer()
输出(这里就和之前对属性直接修改是一样的)
4 继承
- 9.3.1 子类的方法
下面是在前面9.2.1 car类
的基础之上加了个class ElectricCar(Car):
子类,注意子类的写法
class Car():
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""将里程碑度数增加指定的量Add the given amount to the odometer reading."""
self.odometer_reading += miles
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性"""
super().__init__(make,model,year)
my_tesla = ElectricCar("tesla","model s",2016)
print(my_tesla.get_descriptive_name())
# 2016 Tesla Model S
my_tesla.read_odometer()
# This car has 0 miles on it.
(1)对于继承,在前面曾经提及到“9.1.1 创建dog类
的定义中的类的括号是空的,因为我们要从空白中创造这个类”,编写类的时候不一定是总是从空白开始的,如果编写的类是另一个现成类(在前面写好了,且在同一个文档)的特殊版本,就可以继承。
一个类继承另一个类,会获得另一个类的所有属性和方法,原来的类叫做父类,新类叫做子类,子类不仅仅继承了父类的所有属性和方法,还可以创造自己的属性和方法
(2)创建子类的时候,父类必须在当前文件中,且位于子类的前面。定义子类的时候,必须在括号内指定父类的名称。__init__()
接受创建Car实例所需的信息
(3)此外,来自P148,值得注意的是子类在继承父类的时候的写法,super()
是把父类和子类联系起来的方法,调用父类的方法__init__()
让子类继承父类所有的属性。
第一个__init__()
需要接受创建父类实例所需要的信息
接着super()出现了,调用了子类中父类的方法__init__()
,使得子类包含父类的全部属性。
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性"""
super().__init__(make,model,year)
上面是创造子类,接着是给
5 子类属性和方法的定义
- 9.3.3 给子类定义属性和方法
class Car():
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""将里程碑度数增加指定的量Add the given amount to the odometer reading."""
self.odometer_reading += miles
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性"""
super().__init__(make,model,year)
self.battery_size = 70
def describe_battery(self):
"""打印出电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery. ")
my_tesla = ElectricCar("tesla","model s",2016)
print(my_tesla.get_descriptive_name())
# 2016 Tesla Model S
my_tesla.read_odometer()
# This car has 0 miles on it.
my_tesla.describe_battery()
# This car has a 70-kwh battery.
一个类继承另一个类之后,就可以定义新的属性和方法了
可以在9.3.3 给子类定义属性和方法
中看到:
多了个self.battery_size = 70
,所有ElectricCar
类的实例会有这个属性,但是在Car
实例中没有
- 9.3.4 重写父类的方法(对比前)
class Car():
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""将里程碑度数增加指定的量Add the given amount to the odometer reading."""
self.odometer_reading += miles
def fill_gas_tank(self):
"""为了和子类的fill_gas_tank函数形成对比"""
print("我是父类")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性"""
super().__init__(make,model,year)
self.battery_size = 70
def describe_battery(self):
"""打印出电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery. ")
my_tesla = ElectricCar("tesla","model s",2016)
print(my_tesla.get_descriptive_name())
# 2016 Tesla Model S
my_tesla.fill_gas_tank()
# 我是父类
在子类中定义一个和父类方法同名的方法,Python就不会考虑这个父类方法,而是只关注在子类中定义的相应方法。
在9.3.4 重写父类的方法(对比前)
和9.3.4 重写父类的方法(对比后)
中可以得到体现。
- 9.3.4 重写父类的方法(对比后)
class Car():
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""将里程碑度数增加指定的量Add the given amount to the odometer reading."""
self.odometer_reading += miles
def fill_gas_tank(self):
"""为了和子类的fill_gas_tank函数形成对比"""
print("我是父类")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性"""
super().__init__(make,model,year)
self.battery_size = 70
def describe_battery(self):
"""打印出电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery. ")
def fill_gas_tank(self):
"""为了和父类的fill_gas_tank函数形成对比"""
print("This car doesn't need a gas tank!")
my_tesla = ElectricCar("tesla","model s",2016)
print(my_tesla.get_descriptive_name())
# 2016 Tesla Model S
my_tesla.fill_gas_tank()
# This car doesn't need a gas tank!
6 将实例用作属性
- 9.3.5 将实例用作属性(上)
class Car():
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""将里程碑度数增加指定的量Add the given amount to the odometer reading."""
self.odometer_reading += miles
def fill_gas_tank(self):
"""为了和子类的fill_gas_tank函数形成对比"""
print("我是父类")
class Battery():
"一次模拟电动汽车电瓶的简单尝试"
def __init__(self,battery_size = 70):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印出一条描述电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery")
# Battery类没有继承任何类
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性,再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
self.battery = Battery()
# 在ElectricCar类中,添加了一个叫做self.battery的属性
# 这行代码让Python创建了一个新的Battery实例
# 并且把这个实例值存储在属性self.battery中
# 每当__init__被调用,执行操作,每个ElectricCar实例包含一个自动创建的Battery实例
my_tesla = ElectricCar("tesla","model s",2016)
print(my_tesla.get_descriptive_name())
# 2016 Tesla Model S
my_tesla.battery.describe_battery()
# This car has a 70-kwh battery
- 9.3.5 将实例用作属性(下)
class Car():
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述信息Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""打印出一条指出汽车里程的消息Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self,mileage):
"""
Set the odometer reading to the given value.
将里程碑指数设为指定的值
Reject the change if it attempts to roll the odometer back.
禁止里程碑往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""将里程碑度数增加指定的量Add the given amount to the odometer reading."""
self.odometer_reading += miles
def fill_gas_tank(self):
"""为了和子类的fill_gas_tank函数形成对比"""
print("我是父类")
class Battery():
"一次模拟电动汽车电瓶的简单尝试"
def __init__(self,battery_size = 70):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印出一条描述电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery")
# Battery类没有继承任何类
def get_range(self):
"""打印出一条信息,指出电瓶的续航里程"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge"
print(message)
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性,再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
self.battery = Battery()
# 在ElectricCar类中,添加了一个叫做self.battery的属性
# 这行代码让Python创建了一个新的Battery实例
# 并且把这个实例值存储在属性self.battery中
# 每当__init__被调用,执行操作,每个ElectricCar实例包含一个自动创建的Battery实例
my_tesla = ElectricCar("tesla","model s",2016)
print(my_tesla.get_descriptive_name())
# 2016 Tesla Model S
my_tesla.battery.describe_battery()
# This car has a 70-kwh battery
my_tesla.battery.get_range()
# This car can go approximately 240 miles on a full charge
有的时候给类添加的细节越来越多:属性和方法越来越多
就需要把类的一部分作为一个独立的类提取出来,将大类拆分成多个协同工作的小类
比如把针对电瓶汽车属性和方法提取出来,于是在9.3.5 将实例用作属性(上)
创建了Battery()
class Battery():
"一次模拟电动汽车电瓶的简单尝试"
def __init__(self,battery_size = 70):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印出一条描述电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery")
# Battery类没有继承任何类
没有继承任何类,这是独立的一类是,是针对电瓶汽车属性和方法的一个类
此处可以看到Battery()
在定义属性的时候,在__init__()
的括号内不仅仅只有battery_size
,而且还有battery_size=70
,不像之前一样,只是
def __init__(self,battery_size):
或者
def __init__(self,battery_size):
"""初始化电瓶的属性"""
self.battery_size = battery_size
或者是
def __init__(self):
"""初始化电瓶的属性"""
self.battery_size = 70
这部分估计就是要联系到前面的函数了
之后
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性,再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
self.battery = Battery()
出现了self.battery = Battery()
,在super().__init__()
之后
也就是将实例用作属性吧
self.属性名称=类
7 导入类
先编写两个car.py
和cartwo.py
,等会来导入
- car.py
"""A class that can be used to represent a car."""
class Car():
"""A simple attempt to represent a car."""
def __init__(self, manufacturer, model, year):
"""Initialize attributes to describe a car."""
self.manufacturer = manufacturer
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage):
"""
Set the odometer reading to the given value.
Reject the change if it attempts to roll the odometer back.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles
- cartwo.py
"""A class that can be used to represent a car.一个可用于表示汽车的类"""
class Car():
"""A simple attempt to represent a car."""
def __init__(self, manufacturer, model, year):
"""Initialize attributes to describe a car."""
self.manufacturer = manufacturer
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage):
"""
Set the odometer reading to the given value.
Reject the change if it attempts to roll the odometer back.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles
class Battery():
"一次模拟电动汽车电瓶的简单尝试"
def __init__(self,battery_size = 70):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印出一条描述电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery")
def get_range(self):
"""打印出一条信息,指出电瓶的续航里程"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge"
print(message)
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性,再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
self.battery = Battery()
- 9.4.1 导入单个类 my_car
from car import Car
# 虽然是红色,不过还是可以运行的
my_new_car = Car("audi","a4",2016)
print(my_new_car.get_descriptive_name)
# <bound method Car.get_descriptive_name of <car.Car object at 0x00000238255DFC40>>
# 这里少了函数的括号
print(my_new_car.get_descriptive_name())
# 2016 Audi A4
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
# This car has 23 miles on it.
- 9.4.2 在一个模块中存储多个类 my_electric_car
"""A set of classes that can be used to represent electric cars."""
from cartwo import ElectricCar
my_tesla = ElectricCar("tesla","model s",2016)
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
# This car has a 70-kwh battery
# This car can go approximately 240 miles on a full charge
- 9.4.3 在一个模块中导入多个类
from cartwo import Car,ElectricCar
# 导入了两个模块
my_beetle = Car("Volkswagen","beetle",2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar("tesla","roadster",2016)
print(my_tesla.get_descriptive_name())
# 2016 Volkswagen Beetle
# 2016 Tesla Roadster
对上面的导入进行小结:
(1)导入:将类存储在模块中,然后再主程序中导入所需的模块
from 文件名 import 类
(2)import
语句让Python打开模块car
,到导入其中的Car
类
例如
from car import Car
(3)或者导入多个模块
from car import Car,ElectricCar
(4)从一个模块中导入多个类,用逗号分隔各个类
课外补充:"""XXX"""
是文档字符串,描述这串代码是干嘛的
- 9.4.4 导入整个模块
import cartwo
my_beetle = cartwo.Car("volkswagen","beetle",2016)
print(my_beetle.get_descriptive_name())
my_tesla = cartwo.ElectricCar("tesla","roadster",2016)
print(my_tesla.get_descriptive_name())
# 2016 Volkswagen Beetle
# 2016 Tesla Roadster
导入整个模块,再用句点表示法访问需要的类
- 9.4.5 导入所有的类
from module_name import *
这个不推荐,写出来是因为防止看别人的代码的时候会有困惑。
使用这个可能会引发名称方面的困惑,如果不小心导入了一个与程序文件中其他东西同名的类就有问题
需要从一个模块中导入很多类的时候最好是导入整个模块,然后使用module_name.class_name
语法访问类
- 9.4.6 在一个模块中导入另一个模块
有的时候需要把类分散到多个模块,或者在一个模块中存储不相关的类
electric_car
from car import Car
class Battery():
"一次模拟电动汽车电瓶的简单尝试"
def __init__(self,battery_size = 70):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印出一条描述电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kwh battery")
def get_range(self):
"""打印出一条信息,指出电瓶的续航里程"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge"
print(message)
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性,再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
self.battery = Battery()
- 9.4.6 在一个模块中导入另一个模块
from car import Car
from electric_car import ElectricCar
my_beetle = Car("volkswagen","beetle",2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar("tesla","roadster",2016)
print(my_tesla.get_descriptive_name())
# 2016 Volkswagen Beetle
# 2016 Tesla Roadster
可以看到在electric_car
中导入了一个模块,然后在9.4.6 在一个模块中导入另一个模块
又导入了两个模块
Python编程:从入门到实践