知识点
- 类的名字要首字母大写。
- 类由属性和方法组成。
- 类里的函数称为方法。
- 可以用一个类创造多个实例,只要实例名不同即可。
- 类里面的所有方法都需要self参数。
- 子类可以在super().init()语句的括号中添加新的参数,使子类不仅仅是继承父类的所有参数。
- 一个模块中可以存储多个类。
1. 创建一个类
class Dog():
#创建一个Dog类,注意首字母大写和冒号
"""A simple attempt to model a dog.""" #docstring
def __init__(self, name, age):
"""Initialize name and age attributes.""" #docstring
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!")
注意:
- 类名要首字母大写
- 类名后面的括号里面为空,表示这是从零开始创建的类,没有继承其他类
-
--init--()
方法较为特殊,用类创建实例时,自动调用--init--()
方法,其他方法则需要输入代码调用 - 类中的方法必须要有一个
self
参数,且要将self
参数放在最前面 -
--init--()
方法下面定义的变量都要有self前缀,这样可以被类中所有的方法调用 - 可以通过实例查看的变量称为属性
2. 创建一个实例
格式: 实例名=类名(参数)
输入:
class Dog():
---snip--- #Dog类具体细节见上,这=这里省略
my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.") #数字要转为字符
my_dog.sit()
输出:
My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.
(1) 获取属性
格式:instance_name.attribute_name
上例中,生成实例时,括号中的‘Willie’一开始还只是一个字符串,被作为实参传送给类中name形参后,被self.name = name
语句转换为类的属性,并使用my_dog.name
来获取属性的值。
(2)调用方法
格式:instance_name.method_name
上例中,当Python读到my_dog.sit()
,Python为转向Dog类,执行里面的sit()
方法。
3. 使用类和实例
输入:
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
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
return long_name.title()
my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
输出:
2016 Audi A4
(1) 给属性设置默认值
在上例的基础上,添加odometer_reading属性和read_odometer方法,并将odometer_reading属性默认值设为0。
输入:
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 #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.")
my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
输出:
2016 Audi A4
This car has 0 miles on it.
(2) 更改默认值
1.直接法:
格式: instance_name.attribute_name = new_value
输入:
class Car():
---snip---
my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23 #更改默认值
my_new_car.read_odometer()
输出:
2016 Audi A4
This car has 23 miles on it.
2.通过方法更改属性的值
输入:
class Car():
---snip---
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())
my_new_car.update_odometer(300)
my_new_car.read_odometer()
通过类里的update_odometer方法改变属性的值。需要传参。
输出:
2016 Audi A4
This car has 300 miles on it.
4. 继承
类不一定从零开始创建,一个新类可以从另外一个类中继承所有的属性和方法,并且还可以为自己添加新的类和方法。
格式:class child_class (parent_class)
child_class为子类,parent_class为父类。
(1) 利用继承创建一个新类
输入:
class Car():
---snip---
class ElectricCar(Car):
"""Models aspects of a car, specific to electric vehicles."""
def __init__(self, manufacturer, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(manufacturer, model, year)
my_tesla = ElectricCar('tesla', 'roadster', 2015)
print(my_tesla.get_descriptive_name())
输出:
2015 Tesla Roadster
注意:
-
__init__
方法接收创建一个Car类所需的所有参数,并且初始化Car类。 - 初始化Car类后,
super()
函数建立父类与子类的连接,让ElectricCar类继承Car类中所有的方法和属性,super().init(...)语句的括号中,可以添加子类需要的新参数。
(2) 为子类添加属性和方法
可以直接在super().__init__(...)
语句下面添加子类独有的属性。
输入:
class Car():
---snip---
class ElectricCar(Car):
"""Models aspects of a car, specific to electric vehicles."""
def __init__(self, manufacturer, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(manufacturer, model, year)
self.battery_size = 70 #添加新属性,并且设置默认值
def describe_battery(self): #添加新方法
"""Print a statement describing the battery size."""
print("This car has a " + str(self.battery_size) + "-kWh battery.")
my_tesla = ElectricCar('tesla', 'roadster', 2015)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
输出:
2015 Tesla Roadster
This car has a 70-kWh battery.
(3) 重写父类方法
子类会继承父类所有的方法和属性,当某个继承来的方法需要更改时,我们只需要用和原来方法相同的方法名,重新定义方法。
例如,电动车没有油箱,所以我们要把ElectricCar类中的fill_gas_tank方法更改一下。
输入:
class ElectricCar(Car)
---snip---
def fill_gas_tank():
"""electric cars don't have gas tanks"""
print("This car doesn't need a gas tank!")
这样,新的fill_gas_tank方法会覆盖从Car中继承的fill_gas_tank方法。
(4) 将实例作为属性
当属性和方法较多时,可以将一部分属性和方法分离出来,作为单独的类。
输入:
class Car():
---snip---
class Battery():
"""A simple attempt to model a battery for an electric car."""
def __init__(self, battery_size=60):
"""Initialize the batteery's attributes."""
self.battery_size = battery_size
def describe_battery(self):
"""Print a statement describing the battery size."""
print("This car has a " + str(self.battery_size) + "-kWh battery.")
class ElectricCar(Car):
"""Models aspects of a car, specific to electric vehicles."""
def __init__(self, manufacturer, model, year,battery_size):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(manufacturer, model, year)
self.battery = Battery(battery_size)
my_tesla = ElectricCar('tesla', 'roadster', 2015,70)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
输出:
2015 Tesla Roadster
This car has a 70-kWh battery.
上例将与电池相关的属性和方法分离出来,作为一个新类。通过将类Battery的实例作为类ElectricCar的battery属性,将两个类关联起来,虽然类Battery中的参数battery_size默认值为60,却可以由实例my_tesla的实参改为70。
5. 导入类
和函数相同,当程序非常复杂时,我们可以将类单独保存为一个模块,在主程序的开头导入模块即可。
(1)单独导入一个类
导入格式:
from module_name import Class_name
使用格式:
instance_name = Class(arguments)
instance_name.attribute
instance_name.method(arguments)
(2)导入多个类
导入格式:
from module_name import Class1_name,Class2_name,...,Classn_name
使用格式:
instance_name = Class(arguments)
instance_name.attribute
instance_name.method(arguments)
(3)导入整个模块
导入格式:
import module_name
使用格式:
instance_name =module_name.Class(arguments)
instance_name.attribute
instance_name.method(arguments)
只是在用导入的类生成实例时,需要加上module_name,其他时候不需要。
(4)导入模块中所有类(不推荐)
导入格式:
from module_name import *
不推荐这种方法,会弄不清到底使用了哪些类,并且可能造成模块中的类名与主程序的类名冲突。
(5)在一个模块中导入另一个模块
需要用到继承时使用,与主程序导入模块的格式相同
推荐格式:
from module_name import Class_name
6. 类编程风格
- 类名应该采用驼峰命名法,即不使用下划线,每个单词首字母大写
- 实例名和模块名需要小写,单词间用下划线隔开
- 每个类定义的下面都应该紧跟一个docstring,类的每个方法下面也应该有docsting来描述其功能