时间:2018/5/3
主要内容:
类
面向对象编程时最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。 编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后根据需要赋予每个对象独特的个性。根据类来创建对象被称为实例化。
创建和使用类
使用类几乎可以模拟各种东西。
创建Dog类
根据Dog类创建的每个实例都将储存名字和年龄。我们赋予了每条小狗蹲下(sit())和打滚(roll_over())的能力
class Dog():
'''一次模拟小狗的简单尝试'''
def __init__(self,name,age):
'''初始化属性name和age'''
self.name = name
self.age = age
def sit(self):
'''模拟小狗被命令时蹲下'''
print(self.name.title() + ' is now sitting.''')
def roll_over(self):
'''模拟小狗被命令时打滚'''
print(self.name.title() + ' is now rolled over!')
#在第一行定义了一个名为Dog的类。在Python中,首字母大写的名称指的时类。
#方法__init__():类中的函数称为方法;__init__()是一个特殊的方法,每当你根据Dog类创建新例时,Python都会自动运行它。开头结尾各有两个下划线旨在避免Python默认方法和普通方法发生名称冲突。我们将方法__init__()定义成了包含三个形参:self、name和age。形参self必不可少,还必须位于其他形参前面。在类的实例化过程中,将自动传入实参self,每个与类相关联的方法调用都自动传递实参self,他是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
Python中 __init__的通俗解释? - 知乎 点击打开链接
#变量name有前缀self,以self为前缀的变量可以供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。self.name = name 获取储存在形参name中的值,并将其储存在变量name中(!注意等号左右两个name不一样,左边是创建的新变量name,右边指的是形参name)然后该变量被关联到当前创建的实例。
根据类创建实例
class Dog():
'''一次模拟小狗的简单尝试'''
def __init__(self,name,age):
'''初始化属性name和age'''
self.name = name
self.age = age
def sit(self):
'''模拟小狗被命令时蹲下'''
print(self.name.title() + ' is now sitting.''')
def roll_over(self):
'''模拟小狗被命令时打滚'''
print(self.name.title() + ' is now rolled over!')
my_dog = Dog('willie',6)
your_dog = Dog('lucy',3)
print('My dog\'s name is ' + my_dog.name.title() + '.')
print('My dog is ' + str(my_dog.age) + ' years old.')
my_dog.sit()
print('Your dog\'s name is ' + your_dog.name.title() + '.')
print('Your dog is ' + str(your_dog.age) + ' years old.')
your_dog.roll_over()
使用类和实例
Car类
class Car():
'''一次模拟汽车的简单尝试'''
def __init__(self,make,model,year):
'''初试化描述汽车属性'''
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
my_new_car = Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
给属性指定默认值
类中的每个属性都必须有初始值。如设置默认值时,在方法__init__()内指定这种初始值是可行的,如指定默认值,无需为他提供初始值的形参。例如在Car类中添加名为odometer_reading的属性,其初始值是0.添加一个名为read_odometer()的方法,用于读取汽车的里程表:
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):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
'''打印一条指出汽车里程的消息'''
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()
修改属性的值
三种修改方法:直接通过实例进行修改,通过方法进行设置,通过方法进行递增(增加特定的值)。
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):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
'''打印一条指出汽车里程的消息'''
print('This car has ' + str(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
my_new_car = Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
#直接修改属性的值
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
#通过方法修改属性的值
my_new_car.update_odometer(46)
my_new_car.read_odometer()
my_new_car.update_odometer(34)
my_new_car.read_odometer()
#通过方法对属性的值进行递增
my_new_car.increment_odometer(40)
my_new_car.read_odometer()
继承
一个类继承另一个类时,它将自动获得另一个类的所有属性和方法,原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
子类的方法__init__()
创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。
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):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
'''打印一条指出汽车里程的消息'''
print('This car has ' + str(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):
'''电动汽车的独特之处'''
def __init__(self,make,model,age):
'''初始化父类的属性'''
super().__init__(make,model,age)
my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
创建子类时,父类必须包括在当前文件中,且位于子类前面。
定义子类时,必须在括号中指定父类的名称。方法__init__()接受创建Car实例所需的信息。
super()是一个特殊函数,帮助将父类和子类联系起来,这行代码让Python调用ElectircCar的父类方法__init__(),让ElectircCar实例包括父类的所有属性。父类也称为超类(superclass),名称super因此得名。
给子类定义属性和方法
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。
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):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
'''打印一条指出汽车里程的消息'''
print('This car has ' + str(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):
'''电动汽车的独特之处'''
def __init__(self,make,model,age):
'''初始化父类的属性
再初始化电动车特有的属性
'''
super().__init__(make,model,age)
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())
my_tesla.describe_battery()
重写父类的方法
假设现在Car类中有一个名为fill_gas_tank()的方法,它对电动汽车类毫无用处。
class ElectricCar(Car):
--snip--
def fill_gas_tank():
'''电动汽车没有油箱'''
print('This car doesn\'t need a gas tank!')
将实例用作属性
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):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
class Battery():
'''一次模拟电动汽车电瓶的简单尝试'''
def __init__(self,battery_size = 70):
'''初始化电瓶的属性'''
self.battery_size = battery_size
def describe_battery(self):
'''打印一条描述电瓶容量的消息'''
print('This car have a ' + str(self.battery_size) + '-kWh battery.')
class ElectricCar(Car):
'''电动汽车的独特之处'''
def __init__(self,make,model,age):
'''
初始化父类的属性,再初始化电动汽车特有的属性
'''
super().__init__(make,model,age)
self.battery = Battery()
my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
在上面的代码中,在ElectricCar类中,我们添加了一个名为self.battery的属性,这行代码让Python创建一个新的Battery实例(由于没有指定尺寸所以取默认值70),并将该实例储存在属性self.battery中。每当方法__init__()被调用,都将执行该操作;因此现在每个ElectricCar实例中都包括一个自动创建的Battery实例。
导入类
导入单个类
模块car.py
'''一个可用于表示汽车的类'''
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):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
'''打印一条指出汽车里程的消息'''
print('This car has ' + str(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
首行包含了一个模块级文档字符串,对该模块的内容做了简要的描述。
创建另一个文件——my_car.py进行类的导入
from car import Car
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()
在一个模块中储存多个类
创建car.py模块
'''一个可用于表示燃油车和电动车的类'''
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):
'''返回整洁的描述性信息'''
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
'''打印一条指出汽车里程的消息'''
print('This car has ' + str(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():
'''一次模拟电动汽车电瓶的简单尝试'''
def __init__(self,battery_size = 70):
'''初始化电瓶的属性'''
self.battery_size = battery_size
def describe_battery(self):
'''打印一条描述电瓶容量的消息'''
print('This car have 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,age):
'''
初始化父类的属性,再初始化电动汽车特有的属性
'''
super().__init__(make,model,age)
self.battery = Battery()
my_electric_car.py
from car import ElectricCar
my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
从一个模块中导入多个类
语法:
from car import Car,ElectricCar
导入整个模块
语法:
import car
导入模块中的所有类
语法:
from module_name improt *
!参考函数模块的导入
在一个模块中导入另一个模块
有时候,需要将类分散到多个模块中,以免模块太大,或者在同一模块中储存不相关类。
比如我们将电动汽车和汽车模块分离开,在电动汽车模块中导入汽车模块car.py,再在新的文件中导入模块electirc_car.py
自定义工作流程
一开始应该使代码结构尽量简单,先尽量在一个文件中完成所有工作,确定一切都能正常运行后再将类一道独立的模块中去。
Python标准库
安装的python中都含有python标准库(collctions)这一模块。
类编码风格
类命名采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,在单词间使用下划线。
对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种字符串简要的描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应该包含一个文档字符串,对其中的类可用于做什么进行描述。