一.创建和使用类
1)创建类
eg:
class Dog():
def __init__(self, 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() + " rolled over!")
1.方法__init__() (构造函数)(两侧下划线各有两个)
类中的函数称之为方法,__init__
为特殊的方法,每次根据类新建实例时,Python都会自动运行它,该例中定义包含三个形参,self必不可少,且位于所有其他形参之前,通过name和age传递年龄和名字,self会自动传
2.定义另外两个方法,由于不需要额外的信息,因此他们只有一个形参self
2)根据类创建实例
eg:
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
#super().__init__()
def sit(self):
print(self.name.title() + "is now sitting.")
def roll_over(self):
print(self.name.title() + " rolled over!")
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.roll_over()
输出:
My dog's name is Willie.
My dog is 6 years old.
Willieis now sitting.
Willie rolled over!
python使用实参’willie’和6调用Dog类中的方法,__init()__
创建一个表示特定小狗的示例,并根据提供的值设置属性name()和age()
__init()
__并未显示的包含return语句,python会自动返回一个表示特定小狗的实例存储在变量my_dog中
使用句点表示法访问属性如my_dog.name.title()
使用句点表示法调用方法如my_dog.roll_over()
3)创建多个实例
可以根据需求创建任意数量的实例。
eg:
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
#super().__init__()
def sit(self):
print(self.name.title() + " is now sitting.")
def roll_over(self):
print(self.name.title() + " 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()
输出
My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.
Your dog's name is Lucy.
Your dog is 3 years old.
Lucy rolled over!
二.使用类和实例
类编写好后,大部分时间都花在使用根据类创建的实例上,需要执行的一个重要任务就是修改实例的属性,可以直接修改实例的属性,也可以编写方法以特定的方式进行修改
1)Car类
eg1:
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())
输出:
2016 Audi A4
2)给属性指定默认值
类中的每个属性都必须有初始值,哪怕这个值时0或是空字符串,在有些情况下,如设置成默认值时,在方法__init()__
中可以指定初始值,如果指定了初始值,那么就无需包含为它提供初始值的形参
如在上例中加上一个名为odometer_reading的属性,初值为0,再添加一个read_odometer()的方法,用于读取汽车的里程表
eg2:
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) + " mile 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 12 mile on it.
3)修改属性的值
1.直接修改属性的值通过实例直接访问它
eg:
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) + " mile on it.")
my_new_car = Car('audi', 'a4', '2016')
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 20#直接访问修改属性的值
my_new_car.read_odometer()
输出
2016 Audi A4
This car has 20 mile on it.
2.通过方法修改属性的值
在类的内部定义方法,无需直接访问属性,可以将值传递给一个方法,由它在内部更新
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) + " mile 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")
my_new_car = Car('audi', 'a4', '2016')
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(20)
my_new_car.read_odometer()
输出
2016 Audi A4
This car has 20 mile on it.
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):
'''返回简单的描述信息'''
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) + " mile on it.")
def increment_oddmeter(self, miles):
'''将里程表读数增加指定的量'''
self.odometer_reading += miles
my_new_car = Car('audi', 'a4', '2016')
print(my_new_car.get_descriptive_name())
my_new_car.increment_oddmeter(23500)
my_new_car.read_odometer()
my_new_car.increment_oddmeter(100)
my_new_car.read_odometer()
输出:
2016 Audi A4
This car has 23500 mile on it.
This car has 23600 mile on it.
三.继承
编写类时,并非总是要从空白开始。如果你编写的类时另一个线程的类的特殊版本,可以使用继承
1)子类的方法__init()__
创建子类实例时,python首先要做的就是给父类的所有属性赋值。
eg:
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) + " mile 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_oddmeter(self, miles):
'''将里程表读数增加指定的量'''
self.odometer_reading += miles
class Electric(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类属性'''
super().__init__(make, model, year)
my_tesla = Electric('tesla', 'model s', '2016')
print(my_tesla.get_descriptive_name())
输出
2016 Tesla Model S
创建子类时,class Electric(Car):
父类必须包含在当前文件,此例中Car即为子类.
方法__init__()
接受创建Car实例所需的信息
super()函数帮助python将父类与子类联合起来因为父类称为超类(superclass),super因此得名
super().__init__(make, model, year)#这里的super().__init()__()函数里没有self,只有父类函数中需要初始化的属性
这行代码让Python调用ElectricCar的父类的方法__init__()
子类实例化时调用自己的构造函数,该函数又调用父类的构造函数。
2)给子类定义属性与方法
eg:
在上例中添加一个Electric类特有的属性以及Electric类中特有的方法。
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) + " mile 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_oddmeter(self, miles):
'''将里程表读数增加指定的量'''
self.odometer_reading += miles
class Electric(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 = Electric('tesla', 'model s', '2016')
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
输出:
2016 Tesla Model S
This car has a 70-kWh battery.
如果子类中也有需要初始化的属性
eg:
class Restaurant():
def __init__(self, restaurant_name, cuisine_type, number_served = 0):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_served = number_served
class IceCreamStand(Restaurant):
def __init__(self, restaurant_name, cuisine_type, flavors):
super().__init__(restaurant_name, cuisine_type)
self.flavors = flavors
def show_flavors(self):
print(self.flavors)
icecreamstand = IceCreamStand('KFC','fired chicken',['red', 'yellow', 'green'])
icecreamstand.show_flavors()
输出
['red', 'yellow', 'green']
其中flavors做为子类的属性在子类的构造函数中初始化
编写子类构造函数需要将父类需要初始化的函数也传进来,调用super().__inti__()
函数初始化
3)重写父类的方法
对于父类的方法,只要它不符合子类模拟实物的方法,都可以对其进行重写。为此可以在类中定义一个这样的方法,即它与要重写的父类方法同名,这样,Python不会考虑这个父类方法,只关注在子类中定义的相应方法。
子类的实例化对象调用该方法以子类中定义的为准,不考虑父类的定义。
eg:
class Car():
'''一次模拟汽车的简单尝试'''
def __init__(self, make, model, year):
'''初始化汽车的属性'''
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0#给出默认值的属性,在实例化的时候就不需要传参数了
def fill_gas_tank(self):
print("1000")
class Electric(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类属性'''
super().__init__(make, model, year)
self.battery_size = 70#初始化电动汽车的特有属性
def fill_gas_tank(self):#重写父类的方法
print("This car doesn't have a gas tank!")
my_tesla = Electric('tesla', 'model s', '2016')
my_tesla.fill_gas_tank()#调用重写的方法
输出:
This car doesn't have a gas tank!
此时会执行子类中的fill_gas_tank()方法,而不是父类中的fill_gas_tank()方法
4)将实例用作属性
使用代码模拟实物时,类添加的细节越来越多,可以将类的一部分作为一个独立的类提取出来,将大类拆分成多个协同工作的小类。
eg:上例中可以将针对汽车电瓶的属性和方法,提取出来,放在一个Battery的类中,并将一个battery实例作为Electric类的一个属性
eg:
#car类不变,同上例
class Battery():#将battery单独作为一个类
def __init__(self, battery_size = 70):
self.battery_size = battery_size
'''
def __init__(self):
这样的写法同上,将默认值卸载函数体里
self.battery_size = 70
'''
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) + "miles on a full charge"
print(message)
class Electric(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类属性'''
super().__init__(make, model, year)#继承父类
self.battery = Battery()#将Battery实例化一个对象作为Electric的一个属性
def fill_gas_tank(self):#重写父类的方法
print("This car doesn't have a gas tank!")
my_tesla = Electric('tesla', 'model s', '2016')
#my_tesla.fill_gas_tank()#调用重写的方法
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
输出
2016 Tesla Model S
This car has a 70-kWh battery
This car can go approximately 240miles on a full charge
代码self.battery = Battery()
将Battery实例化为Electric类下的一个属性,(与从父类继承来的属性与自己定义的属性性质一样)该属性可以去调用Battery类中的两个方法,并且如果不给出初始值,self.battery.battery_size会被初始化为70
四.导入类
随着不断给类添加功能,文件可能变得很长,遵循python的总体理念,应该让文件尽可能整洁,python允许将类存储在模块中,然后再主程序中导入
1)导入单个类
eg:
#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) + " mile 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_oddmeter(self, miles):
'''将里程表读数增加指定的量'''
self.odometer_reading += miles
def fill_gas_tank(self):
print("1000")
#mycar.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()
输出
2016 Audi A4
This car has 23 mile on it.
在mycar.py文件中使用from car import Car
打开模块car并导入Car类,就可以使用了
2)在一个模块中存储多个类
eg:
#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) + " mile 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_oddmeter(self, miles):
'''将里程表读数增加指定的量'''
self.odometer_reading += miles
def fill_gas_tank(self):
print("1000")
class Battery():
def __init__(self):
self.battery_size = 70
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) + " miles on a full charge"
print(message)
def upgrade_bettery(self):
if self.battery_size != 85:
self.battery_size = 85
class Electric(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类属性'''
super().__init__(make, model, year)#继承父类
self.battery = Battery()#将Battery实例化一个对象作为Electric的一个属性
def fill_gas_tank(self):#重写父类的方法
print("This car doesn't have a gas tank!")
#my_electric.py
from car import Electric#从car.py中导入Electric类
my_tesla = Electric('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
输出
2016 Tesla Model S
This car has a 70-kWh battery
This car can go approximately 240 miles on a full charge
3)从一个模块中导入多个类
car.py同上
#my_car.py
from car import Car,Electric#从car.py中导入Car和Electric两个类
my_beetle = Car('volkswagen', 'bettle', 2016)#Car的实例化
print(my_beetle.get_descriptive_name())
my_tesla = Electric('tesla', 'roadster', 2016)#Electric的实例化
print(my_tesla.get_descriptive_name())
输出
2016 Volkswagen Bettle
2016 Tesla Roadster
4)导入整个模块
#my_car.py
import car#导入整个模块
my_beetle = car.Car('volkswagen', 'bettle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = car.Electric('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
输出
2016 Volkswagen Bettle
2016 Tesla Roadster
5)导入模块中的所有类
from module_name import*
不推荐使用,容易混淆或者引发冲突
如果需要导入一个模块中的很多类,最好导入整个模块,并使用moudle_name.class_name
来访问类,这样可以清楚的知道那些地方使用了导入的模块,避免了导入模块中的每个类可能引发的名称冲突。
6)在一个模块中导入另一个模块
#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) + " mile 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_oddmeter(self, miles):
'''将里程表读数增加指定的量'''
self.odometer_reading += miles
def fill_gas_tank(self):
print("1000")
#electric.py
from car import Car
class Battery():
def __init__(self):
self.battery_size = 70
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) + " miles on a full charge"
print(message)
def upgrade_bettery(self):
if self.battery_size != 85:
self.battery_size = 85
class Electric(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类属性'''
super().__init__(make, model, year)#继承父类
self.battery = Battery()#将Battery实例化一个对象作为Electric的一个属性
def fill_gas_tank(self):#重写父类的方法
print("This car doesn't have a gas tank!")
#my car.py
from car import Car
from electric_car import Electric
my_beetle = Car('volkswagen', 'bettle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = Electric('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
输出:
2016 Volkswagen Bettle
2016 Tesla Roadster
五.Python标准库
Python标准库是一组模块,安装的python都包括它,可以使用标准库中任何的函数和类,只需要在函数开始包含一条简单的import语句。
六.类编码风格
1.类名使用驼峰命名法,类名中的每个单词首字母都大写,不使用下划线,实例名与模块名都小写,单词之间加上下划线。
2.每个类,在类定义后面包含一个文档字符串,简要的描述类的作用,每个模块包含一个文档字符串,对其中的类做什么进行描述。
3.在类中,使用一个空行来分隔方法,模块中,使用两个空行来分割类。
4.需要同时导入标准库和自己编写的模块,先编写导入标准库的import语句,再添加一个空行,然后编写导入自己的模块的import语句。