- 根据类来创建对象被称为实例化。
创建类和使用类
1.创建Dog类
- 在python中,首字母大写的名称指的是类。这个类的定义中的括号是空的,因为我们要从空白来创建这个类。
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 rool_over(self):
"""模拟小狗被命令时打滚"""
print(self.name.title()+" rolled over.")
1.方法__init__ ()
- 类中的函数称为方法。
- 方法__init__ ()是一个特殊的方法,每当根据Dog类创建新实例时,python都会自动运用它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,避免python默认方法与普通方法发生名称冲突。
- 它包含三个形参:self、name和age。在这个方法的定义中,self必不可少,并且还必须位于其他形参的前面。每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
- 我们通过实参向Dog()传递名字和年龄,self会自动传递,因此我们不需要再传递它。当我们根据Dog类来创建实例时,都只需给最后两个形参(name和age)提供值。
self.name=name
self.age=age
以self为前缀的变量都可供类中的所有方法使用,我们可以通过类的任何实例来访问这些变量,self.name=name
获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。
2.根据类创建实例
- 首字母大写的名称指的是类,小写的名称指的是根据类创建的实例。
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's name is Willie.
My dog is 6 years old.
python使用实参‘willie’和6调用Dog类中的方法__init__ ()。这个方法创建一个表示特定小狗的实例,并使用我们提供的值来设置属性name和age。我们将这个实例存储在变量my_dog中。
1.访问属性
- 要访问实例的属性,可使用句点表示法。
my_dog.name
。演示了python如何获悉属性的值。在这里,python先找到实例my_dog,再查找与这个实例相关联的属性name.在Dog类中引用这个属性时,使用的是self.name
2.调用方法
- 根据Dog类创建实例后,就可以使用句点表示法来调用Dog类中定义的任何方法。
my_dog = Dog('willie',6)
my_dog.rool_over()
my_dog.sit()
Willie rolled over.
Willie is now sitting.
3.创建多个实例
- 可按需求根据类创建任意数量的实例。
使用类和实例
1.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)+' '+ str(self.make)+' '+str(self.model)
return long_name
my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
2016 audi a4
2.给属性指定默认值
- 类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。
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)+' '+ str(self.make)+' '+str(self.model)
return long_name
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()
2016 audi a4
This car has 0 miles on it
添加一个名为odometer_reading的属性,初始值为0,
self.odometer_reading=0
3.修改属性的值
- 直接修改属性的值
- 要修改属性的值,最简单的方法是通过实例直接访问它。
my_new_car.odometer_reading=23
my_new_car.read_odometer()
使用句点表示法直接访问并设置汽车的属性odometer_reading.
- 通过方法进行设置
- 更新属性
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.update_odometer(23)
my_new_car.read_odometer()
添加方法
update_odometer()
,接受一个里程值,并将其存储到self.odometer_reading
中,调用update_odometer
,并向它提供实参23,update_odometer()
在修改属性前检查指定的读数是否合理,如果新指定的里程数mileage大于或等于原来的里程self.odometer_reading,就将里程读数改为新指定的里程,否则发出警告。
将里程表读数设置为23,方法read_odometer()
打印该读数。
- 通过方法进行递增(增加特定的值)
- 将属性值递增特定的量,而不是将其设置为全新的值。
def increment_odometer(self,miles):
"""将里程表读数增加指定的量"""
self.odometer_reading += miles
my_new_car.increment_odometer(100)
my_new_car.read_odometer()
2016 audi a4
This car has 23 miles on it
This car has 123 miles on it
继承
- 一个类继承另一个类的时候,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。子类继承父类的所有属性和方法,还可以定义自己的属性和方法。
1.子类的方法_init_()
- 创建子类的实例时,python首先需要完成的人物就是给父类的所有属性赋值。
- 创建子类时,父类必须包含在当前文件中,且位于子类前面
- 定义子类时,必须要在括号内指明父类的名称。
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):
"""返回整洁的描述性信息"""
long_name=str(self.year)+' '+ str(self.make)+' '+str(self.model)
return long_name
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,year):
"""初始化父类中的属性"""
super().__init__(make,model,year)
my_tesla=ElectricCar('tesla','modle s',2016)
print(my_tesla.get_descriptive_name())
2016 tesla modle s
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)+' '+ str(self.make)+' '+str(self.model)
return long_name
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,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','modle s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
2016 tesla modle s
This car has a 70-kwh battery.
添加新属性
self.battery_size
,设置其初始值为70。ElectricCar类创建的所有实例都包含这个属性,但所有的Car的实例都不包含它。
3.重写父类的方法
- 在子类中定义一个方法,它与要重写的父类的方法同名,这样,python将不会考虑这个父类方法,只关注你在子类中定义的相应方法。
4.将实例用作属性
- 如果要给类添加的细节越来越多时,可将类的一部分作为一个独立的类提取出来。
- 在不断给ElectricCar类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶的属性和方法,将这个属性和方法提取出来,放到另一个名为Battery的类中,并将一个Battery实例用作ElectricCar类的一个属性。
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.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类中的属性
再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
self.battery=Battery()
my_tesla=ElectricCar('tesla','modle s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
定义一个名字为Battery的新类,它没有继承任何类,提供
__init__()
方法,除了self
外,还有另一个形参battery_size
,它是可选,如果没有给它提供值,电瓶容量将被设置为70。
self.battery=Battery()
,在ElectriCar类中,添加了一个名为self.battery
的属性,这行代码创建了一个新的Battery的实例,并将该实例存储在属性self.battery
中,每当方法_init_()被调用时,都将执行该操作。
my_tesla.battery.describe_battery()
,让python在实例my_tesla中查找属性battery,并对存储在该属性中的Battery实例调用方法describe_battery()。
9-8权限
class User():
def __init__(self,first_name,last_name):
self.first_name=first_name
self.last_name=last_name
self.login_attempts=0
def describe_user(self):
print("Your first name is:" + self.first_name.title())
print("Your Last name is:" + self.last_name.title())
def greet_user(self):
full_name = self.first_name + self.last_name
print("Hello, " + full_name.title()+". Glad to hear you.")
def incerement_login_attempts(self):
"""将属性login_attempts的值加1"""
self.login_attempts += 1
print("The user's login attempts is "+ str(self.login_attempts)+".")
def reset_login_attempts(self):
self.login_attempts=0
print("The user's login attemptes is "+ str(self.login_attempts)+".")
class Privileges():
def __init__(self,privileges = ['can add post', 'can delete post', 'can ban user']):
self.privileges=privileges
def show_privileges(self):
print("The Admin has some privileges: ")
for n in self.privileges:
print(n)
class Admin(User):
def __init__(self,first_name,last_name):
super().__init__(first_name,last_name)
self.privileges=Privileges()
admin=Admin('zhang','huijuan')
admin.greet_user()
admin.privileges.show_privileges()
9-9 电瓶升级
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)+' '+ str(self.make)+' '+str(self.model)
return long_name
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 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)
def upgrade_battery(self):
"""检查电瓶容量并设置
注意区分self.battery_size和battery_size"""
if self.battery_size != 85:
self.battery_size = 85
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类中的属性
再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
self.battery=Battery()
my_tesla=ElectricCar('tesla','modle s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.upgrade_battery()
my_tesla.battery.get_range()
导入类
- python允许将类存储在模块中,然后在主程序中导入需要的模块。
1.导入单个类
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)+' '+ str(self.make)+' '+str(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()
2016 Audi A4
This car has 23 miles on it
2.在一个模块中存储多个类
- 虽然同一模块中的类之间存在某种相关性,但可根据需要在一个模块中存储任意数量的类。
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)+' '+ str(self.make)+' '+str(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 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)
def upgrade_battery(self):
"""检查电瓶容量并设置
注意区分self.battery_size和battery_size"""
if self.battery_size != 85:
self.battery_size = 85
class ElectricCar(Car):
"""模拟电动汽车的独特之处"""
def __init__(self,make,model,year):
"""初始化父类的属性
再初始化电动汽车特有的属性"""
super().__init__(make,model,year)
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()
3.从一个模块导入多个类
- 可根据需要在程序文件中导入任意数量的类。
from Car import Car,ElectricCar
将Car类和ElectricCar类都导入。 - 从一个模块中导入多个类时,用逗号分隔开各个类,导入必要的类后,就可根据需要创建每个类的任意数量的实例。
4.导入整个模块
- 导入整个模块,使用句点表示法访问需要的类。
导入整个Car模块
import Car
my_new_car=Car.Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading=23
my_new_car.read_odometer()
print("\n")
my_tesla=Car.ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
5.导入模块中的所有类
from Car import *
,导入Car模块中的所有的类。- 不建议使用这种导入方式。这种方式没有明确指出使用了模块中的哪些类,还可能引发名称方面的困惑。
- 需要从一个模块中导入很多类时,最好是导入整个模块,并使用
module_name.class_name
语法来访问类。
6. 从一个模块中导入到另一个模块
- 将类分散到多个模块中,避免模块太大
from Car import Car
from ElectricCar import ElectricCar
my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
my_tesla=ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
python标准库
- python标准库是一组模块。
- 模块collections中的一个类——OrderedDict
- 要创建字典并记录其中的键-值对的添加顺序,可使用模块collections中的OrderedDict类。OrderedDict实例的行为几乎与字典相同,区别只在于记录了键-值对的添加顺序。
from collections import OrderedDict
favorite_languages=OrderedDict()
favorite_languages['jen']='python'
favorite_languages['sarach']='c'
favorite_languages['edward']='ruby'
favorite_languages['phil']='python'
for name,language in favorite_languages.items():
print(name.title()+"'s favorite language is "+language.title()+".")
Jen's favorite language is Python.
Sarach's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Python.
从模块
collections
中导入了OrderedDice类
,这个类兼具列表和字典的主要优点(在将信息关联起来的同时保留原来的顺序)
9-14骰子
from random import randint
class Die():
def __init__(self,sides=6):
self.sides=sides
def roll_die(self):
print(randint(1,self.sides))
my_dict=Die(6)
for n in range(1,11):
my_dict.roll_die()
类编码风格
- 类名中的每个单词的首字母都要大写,而不使用下划线,实例名和模块名都采用小写形式并在单词之间加上下划线,
- 对于每个类,都应紧跟在类定义后面包含一个文档字符串,这种字符串简要描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
- 需要同时导入标准库中的模板和你编写的模板时,先编写导入标准库的import语句,再添加一个空行,然后编写导入你自己编写的模块的import语句。