Python蟒蛇书学习笔记——第九章 类
Python蟒蛇书学习笔记——第九章 类
#初稿完成时间:2022/7/3
#作者:XP钉子户
面向对象编程 是Python语言特色之一。编写类 时,可以提前设计好各种通用行为。基于类所创建的对象 均拥有此类通用行为,根据类来创建对象称为实例化 。
下面为本笔记的目录,可以点击目录跳转到对应的部分阅读。
文章目录
- Python蟒蛇书学习笔记——第九章 类
-
-
9.1 创建和使用类
-
9.2 根据类创建实例
-
- 9.2.1 类创建实例的方法
- 9.2.2 访问实例的属性和调用实例的方法
- 9.2.3 给属性指定默认值
- 9.2.4 修改属性的值
-
9.3 继承
-
- 9.3.1 子类的继承与定义属性和方法
- 9.3.2 重写父类的方法
- 9.3.3 将实例用作属性
-
9.4 导入类
-
- 9.4.1 导入单个类
- 9.4.2 在一个模块中存储多个类
- 9.4.3 从一个模块中导入多个类
- 9.4.4 导入整个模块
- 9.4.5 导入模块中的所有类
- 9.4.6 使用别名
-
9.5 Python标准库
-
9.5 Python标准库
-
9.1 创建和使用类
创建类的方法:
class Dog:
def __init__(self,name,age):
"""初始化函数,每次根据Dog类创建新实例时,Python都会自动运行它。"""
self.name=name
self.age=age
def sit(self):
print(f"{self.name} is now sitting.")
def roll_over(self):
print(f"{self.name} rolled over!")
注意:此处出现了self 。self类似于Java语言内的this ,只出现在类里面(换言之,实例化之后就不会出现self)。以self为前缀的变量可供类中的所有方法使用,可以通过任何类的实例来访问。如:
my_dog = Dog('Willie',6) #实例化一个对象my_dog
print(my_dog.name)
print(my_dog.age)
此时程序的输出为:
willie
6
像这种可以通过实例访问的变量称为属性 。
9.2 根据类创建实例
9.2.1 类创建实例的方法
根据类创建实例的方法:
class Dog:
...
my_dog = Dog('willie',6) #这里的'willie'为name变量的初始值,6为age变量的初始值
此处通过Dog类创建了一个my_dog实例。这个创建过程中赋予了两个实参,在实例化时,Python会自动执行Dog类里面的初始化函数,并根据这个函数对my_dog的参数进行初始化。
Python也支持对同一个类创建多个实例。每个实例都拥有着类别相同的属性。
9.2.2 访问实例的属性和调用实例的方法
下面,我们对于my_dog实例访问属性和调用方法。
print("My dog's name is {}".format(my_dog.name))
print("My dog's age is {}".format(my_dog.age))
my_dog.sit()
my_dog.roll_over()
程序的运行结果如下:
My dog's name is willie
My dog's age is 6
willie is now sitting.
willie rolled over!
9.2.3 给属性指定默认值
可以通过在类的初始化函数中直接赋予self的某个属性默认值。如:
class Dog:
def __init__(self,name,age): #此处可以设定形参sex,也可以不设定。
self.name=name
self.age=age
self.sex='male'
def get_sex(self):
print("Your dog's sex is {}.".format(self.sex))
my_dog=Dog('willie',6)
my_dog.get_sex()
程序的运行结果如下:
Your dog's sex is male.
9.2.4 修改属性的值
修改属性的值有两种方法。
首先可以通过实例直接访问。如:
class Dog:
...
my_dog=Dog('willie',6)
my_dog.sex='female' #直接通过实例访问
my_dog.get_sex()
程序的运行结果如下:
Your dog's sex is female.
其次,可以在类里面定义一个修改属性的方法,使用实例时调用其方法来修改属性的值。如:
class Dog:
def __init__(self,name,age): #此处可以设定形参sex,也可以不设定。
self.name=name
self.age=age
self.sex='male'
def change_sex(self,sex): #修改狗狗的性别,若不符合标准则报错
if(sex=='male' or sex=='female'):
self.sex=sex
else:
print("Sorry, the third sex is not supported now.")
def get_sex(self):
print("Your dog's sex is {}.".format(self.sex))
my_dog=Dog('willie',6)
print("Before changes:")
my_dog.get_sex()
s = input("Input {}'s sex:".format(my_dog.name))
my_dog.change_sex(s)
print("After changes:")
my_dog.get_sex()
程序输出如下:
Before changes:
Your dog's sex is male.
Input willie's sex:female
After changes:
Your dog's sex is female.
9.3 继承
编写类时,不一定都要从头开始编写。如果要编写的类是一个现有的类的特殊版本,那么可以使用继承 。一个类继承另一个类时,将自动获得原有的类的所有属性和方法。
原有的类叫做父类 ,新建的类叫做子类 。子类不仅继承了父类的所有方法,同时还可以定义属于自己的属性和方法。显然,子类拥有父类所有的属性和方法,而父类不一定拥有子类所有的属性和方法。
9.3.1 子类的继承与定义属性和方法
继承新类时,通常要调用父类的方法__init__()。这将初始化在父类__init__()中定义的所有属性,从而让子类也包含这些属性。
例如,我们根据已有的Dog类,新建一个Chinese_Dog类,并让Chinese_Dog类继承Dog类。
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
self.sex='male'
class Chinese_Dog(Dog): #让Chinese_Dog类继承Dog类
def __init__(self,name,age,Chinese_name): #定义子类的初始化函数
super().__init__(name,age) #调用父类的初始化函数,参数不用再加self哦
self.Chinese_name=Chinese_name #在父类初始化函数的基础上,初始化子类特有的参数
def Get_Basic_Info(self): #定义子类特有的方法
print(my_Chinese_dog.name)
print(my_Chinese_dog.age)
print(my_Chinese_dog.Chinese_name)
my_Chinese_dog=Chinese_Dog('johnson',5,'wangcai')
my_Chinese_dog.Get_Basic_Info()
程序输出如下:
johnson
5
wangcai
super()是一个特殊的函数,其能调用父类的方法。叫super的原因是:父类的别名是 超类(superclass)。
9.3.2 重写父类的方法
对于父类的方法,如果某些方法对于子类不再适用,就可以进行重写 。为此,可在子类中定义一个与要重写的父类方法同名的方法。这样,Python就不会考虑同名的父类方法,而只关注你在子类中所定义的这个同名方法。
例如,对于以下类,如果我们不对父类的Show_Nation()函数重写:
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
def Show_Nation(self):
print("{} is from the United States.".format(self.name))
class Chinese_Dog(Dog):
def __init__(self,name,age,Chinese_name):
super().__init__(name,age)
self.Chinese_name=Chinese_name
my_dog=Chinese_Dog('Johnson',5,'wangcai')
my_dog.Show_Nation()
此时程序的输出如下:
Johnson is from the United States.
很显然,对于中国的狗狗来说,籍贯应该归为中国。因此,在子类中,要对父类的Show_Nation()函数重写:
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
def Show_Nation(self):
print("{} is from the United States.".format(self.name))
class Chinese_Dog(Dog):
def __init__(self,name,age,Chinese_name):
super().__init__(name,age)
self.Chinese_name=Chinese_name
def Show_Nation(self): #重写父类的Show_Nation()函数
print("{} is from the People's Republic of China.".format(self.name))
my_dog=Chinese_Dog('Johnson',5,'wangcai')
my_dog.Show_Nation()
程序输出如下:
Johnson is from the People's Republic of China.
9.3.3 将实例用作属性
对于一个类来说,如果类里面的属性和方法过于冗杂,可以考虑将类的一部分提取出来作为一个独立的类。可以将大型类拆分成多个协同合作的小类。
例如,对于下面的Dog类:
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
self.nation='China'
self.province='Hainan'
self.city='Haikou'
def Show_Address(self):
print(f"{self.name} is from:")
print(f"{self.city} City,{self.province} Province, {self.nation}")
这个类里面包含了三个关于地址的参数还有一个方法,我们可以把它们单独提取出来,在Dog类之前新建一个address类:
class address: #将原有Dog类里面关于地址的参数和方法提取到address类里面
def __init__(self,nation="China",province='hainan',city='haikou'):
self.nation=nation
self.province=province
self.city=city
def Show_Address(self):
return ("{} City, {} Province, {}".format(self.city,self.province,self.nation))
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
self.Address=address() #创建一个名为Address的实例,并把Address实例当做Dog类的属性
my_dog=Dog('willie',5)
print(my_dog.name.title()+" is from:")
print(my_dog.Address.Show_Address().title()) #在实例my_dog中查找属性address,并对存储在该属性中的address实例调用方法
程序的输出为:
Willie is from:
Haikou City, Hainan Province, China
在这个例子里面,我们把有关地址的参数和方法单独放在了address类里面,然后又在Dog类里面创建一个名为Address的实例,并把Address实例当做Dog类的属性。
需要注意的是:这样单独提取的类必须放在原有类的前面!
9.4 导入类
前面我们学过,可以将程序中的一部分函数保存在另一个同文件目录下的py文件,然后通过import的方式导入源程序中。对于类,Python也支持这样的操作:可以将类存储在模块中,然后在主程序中导入所需的模块。
9.4.1 导入单个类
我们来尝试一下在主程序中导入单个类。
设主程序名为main.py,其源代码为:
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
def Show_Nation(self):
print("{} is from the United States.".format(self.name.title()))
my_dog=Dog('willie',6)
my_dog.Show_Nation()
我们现在将Dog类单独放在名为dog.py的文件中(该文件与main.py放置在同一目录下)。
此时dog.py的源代码为:
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
def Show_Nation(self):
print("{} is from the United States.".format(self.name.title()))
main.py的源代码为:
from dog import Dog #from后面为所打开的模块名称,import后面为所导入的类名
my_dog=Dog('willie',6)
my_dog.Show_Nation()
运行main.py,程序输出为:
Willie is from the United States.
9.4.2 在一个模块中存储多个类
Python支持在一个模块中存储任意数量的类,当然也包括若干子类和父类。
例如,我们运用原来学过的继承的知识,在dog.py中同时存储父类和子类:
class Dog:
def __init__(self,name,age):
self.name=name
self.age=age
def Show_Nation(self):
print("{} is from the United States.".format(self.name))
class Chinese_Dog(Dog):
def __init__(self,name,age,Chinese_name):
super().__init__(name,age)
self.Chinese_name=Chinese_name
def Show_Nation(self): #重写父类的Show_Nation()函数
print("{} is from the People's Republic of China.".format(self.name))
在main.py中,我们新建一个子类的实例,然后调用子类的方法:
from dog import Chinese_Dog #主程序只实例化了Chinese_Dog类,因此导入子类即可
my_dog=Chinese_Dog('Johnson',5,'wangcai')
my_dog.Show_Nation()
程序输出如下:
Johnson is from the People's Republic of China.
9.4.3 从一个模块中导入多个类
从一个模块中导入两个类的方法如下:
from dog import Chinese_Dog,Dog
由此可类推导入三个乃至多个类的方法。
9.4.4 导入整个模块
从一个模块中导入所有类的方法如下:
import dog
需要注意的是,导入整个模块后,要使用句点表示法来访问所需要的类。还是以9.4.2为例,若main.py的首行改为导入dog模块,则后面访问dog模块里面的Chinese_Dog类时应改成:
my_dog=dog.Chinese_Dog('Johnson',5,'wangcai')
my_dog.Show_Nation()
9.4.5 导入模块中的所有类
可以使用通配符*来导入所有的类:
from dog import *
然而并不推荐这么做 ,原因有二:首先,这种写法不能让程序员很直观地看出使用了dog模块的哪些类;其次,如果导入的不同模块之间有同名的类(例如模块1和模块2中都有dog类),则主程序会发生难以预测的错误。因此,建议根据9.4.4的做法,导入整个模块,然后使用句点表示法来访问 ,这样可以大大避免同名而造成的指代不清的问题。
9.4.6 使用别名
可以在导入时通过as来制定别名。例如:
from dog import Chinese_Dog as CD
my_dog=CD('willie',6,'wangcai')
9.5 Python标准库
Python标准库是安装Python时默认包含的一些模块,可以通过import来导入标准库模块,从而自由使用里面的类和函数。例如,调用Python标准库模块random:
from random import randint
print(randint(1,100)) #随机生成一个位于(1,100)区间内的整数
在模块random中,还有一个函数名为choice()。它以一个列表或元组为参数,随机返回其中一个元素:
from random import choice
pets=['dog','cat','mouse','rabbit','pig','sheep']
print('I will choose a pet irregularly.')
print(f'I choose {choice(pets)}.')
9.5 Python标准库
Python标准库是安装Python时默认包含的一些模块,可以通过import来导入标准库模块,从而自由使用里面的类和函数。例如,调用Python标准库模块random:
from random import randint
print(randint(1,100)) #随机生成一个位于(1,100)区间内的整数
在模块random中,还有一个函数名为choice()。它以一个列表或元组为参数,随机返回其中一个元素:
from random import choice
pets=['dog','cat','mouse','rabbit','pig','sheep']
print('I will choose a pet irregularly.')
print(f'I choose {choice(pets)}.')
