第9章 类
根据类来创建对象称为实例化
1.创建和使用类
class Dog:
"""A simple attempt to model a dog."""
def __init__(self, name, age):
"""Initialize name and age attributes."""
self.name = name
self.age = age
def sit(self):
"""Simulate a dog sitting in response to a command."""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command."""
print(f"{self.name} rolled over!")
方法__ init __()
类中的函数称为方法,__ init __()是一种特殊方法, 类似java中构造方法,进行初始化操作
方法__ init __()定义成包含三个形参:self、name和age。
形参self必不可少,而且必须位于其他形参的前面因为python这个方法来创建dog实例时,将自动传入实参self,每个与实参相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
形参self会自动传递,因此不需要传递它,每当根据dog类创建实例时,都只需要给出最后两个形参提供值
以self为前缀的变量可供类中所有方法使用
self.name=name获取与形参name相关联的值,并将其赋给变量name,然后该变量被关联到当前创建的实例。
可以通过实例访问的变量称为属性
根据类创建实例
命名约定:通常可认为首字母大写的名称指的是类,而小写的名称指的是根据类创建的实例
1.访问属性
使用句点表示法
my_dog.name
2.调用方法
根据dog类创建实例后,就能使用句点表示法来调用dog类中定义的任何方法了
要调用方法,可指定实例的名称和要调用的方法,并用句点分隔
3.创建多个实例
2.使用类和实例
给属性指定默认值
创建实例时,有些属性无须通过形参来定义,可在方法__ init __()中为其指定默认值
修改属性的值
1.直接修改属性的值
通过实例直接访问属性,进行修改
2.通过方法修改属性的值
使用方法更新属性,无须直接访问属性,而可将值传递给方法,由它在内部进行更新
def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles
3.通过方法对属性的值进行递增
+=
3.继承
如果要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,将自动获得另一个类的所有属性和方法。原有的类称为父类,而新的类称为子类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。
class Car:
"""A simple attempt to represent a 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):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
self.odometer_reading += miles
class ElectricCar(Car):
"""Represent aspects of a car, specific to electric vehicles."""
def __init__(self, make, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(make, model, year)
self.battery_size = 75#给子类定义属性和方法
def describe_battery(self):#给子类定义属性和方法
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
子类的方法 __ init__()
在既有类的基础上编写新类时,通常要调用父类的方法__ init __ (),这将初始化在父类 __ init __()方法中定义的所有属性,从而让子类包含这些属性
- 创建子类时,父类必须包含在当前文件中,且位于子类前面
- 定义子类时,必须在圆括号内指定父类的名称
- super()是一个特殊函数,让你能够调用父类的方法,父类也称超类
给子类定义属性和方法
见上文
将实例用作属性
class Car:
"""A simple attempt to represent a 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):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
self.odometer_reading += miles
class Battery:
"""A simple attempt to model a battery for an electric car."""
def __init__(self, battery_size=75):#这个形参是可选的,如果没有给它提供值,电瓶容量将被设置为75
"""Initialize the battery's attributes."""
self.battery_size = battery_size
def describe_battery(self):
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")
def get_range(self):
"""Print a statement about the range this battery provides."""
if self.battery_size == 75:
range = 260
elif self.battery_size == 100:
range = 315
print(f"This car can go about {range} miles on a full charge.")
class ElectricCar(Car):
"""Represent aspects of a car, specific to electric vehicles."""
def __init__(self, make, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(make, model, year)
self.battery = Battery()#在实例my_tesla中查找属性battery,并对存储在该属性中的Battery实例调用方法descriibe_battery()
def describe_battery(self):
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
4.导入类
允许将类存储在模块中,然后在主程序中导入所需的模块
导入单个类
from car import Car
在一个模块中存储多个类
可以根据需要在一个模块中存储任意数量的类
从一个模块中导入多个类
from car import Car,ElectricCar
导入整个模块
使用句点表示法访问需要的类,因为创建实例的代码都包含模块名,所以不会与当前文件使用的任何名称发生冲突
import car
my_beetle = car.Car('volkswagen', 'beetle', 2019)#使用句点表示法
print(my_beetle.get_descriptive_name())
my_tesla = car.ElectricCar('tesla', 'roadster', 2019)
print(my_tesla.get_descriptive_name())
导入模块中的所有类
from module_name import *
不推荐
需要从一个模块中导入很多类时,最好导入整个模块,并使用module_name.ClassName语法来访问类
在一个模块中导入另一个模块
有时需要将类分散到多个模块中,以免模块太大或在同一个模块中存储不相关的类
from car import Car
from electric_car import ElectricCar
使用别名
from electic_car import ElectricCar as EC
5.python标准库
>>> from random import randint
>>> randint(1,6)
5
>>> from random import choice
>>> players =['charles','martina',
... ]
>>> first_up = choice(players)
>>> first_up
'martina'
6.类编码风格
类名应采用驼峰命名法,每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线