第五讲:函数与类库

第五讲:函数与类库

第五讲:函数与类库

函数

定义

函数就是代码块,只不过我们给这个代码块特地进行命名,固定住它以后就

用来干某个具体的工作。

当我们需要用程序多次执行同一项任务时,就会需要反复编写完成该任务的代码,这将会使我们的代码变得冗长繁杂,所以函数诞生了。我们只需要把这个需要反复编写的代码块定义为某个函数并命名,使用的时候只需要调用它的名字,即可反复执行任务。所以函数的优点是能够通过代码复用是的程序本身的编写、阅读、测试、修复和改进更加简易。

函数定义格式:

python 复制代码
def text(id):
    a = id + "真厉害!"
    return print(a)

text("xqs")
text("123")
text("1234")

函数名为 text,参数为 id,函数作用为输出简单的称呼,函数体为 S = id + "真厉害!" ,返回值为 print(a) 。函数调用为text("xqs") text("123")。

实参与形参

函数text(id)要求给id指定一个值。当我们调用这个函数并给定值的时候,它就会输出感恩话语。

其实,在函数text(id)的定义中,变量id是一个形参------形式上的参数,即函数执行任务所需的一项信息。在函数调用text("xqs")的时候,我们向形参传递了一个实参------实际参数,即函数执行任务所拥有的一项信息------"xqs",此时实参"xqs"被储存在形参id中。同理,函数调用text("123")时,实参"123"被储存在形参id中;函数调用text("1234")时,实参"1234"被储存在形参id中。

实参

由于函数定义中可能会含有多个形参,因此函数调用中也需要输入多个实参。向形参传递实参的方式主要有两种:位置实参和关键字实参。

  1. 位置参数
    在调用参数函数时,必须将每个形参都赋值为每个实参。最简单的关联方式是基于形参的位置顺序传递实参,这种关联方是成为位置参数。
python 复制代码
def thank_you(something, name):
    R = "You help me with " + something + "." + name
    S = "Thank you," + name
    return print(R,S)

thank_you("Chinese","xqs")
thank_you("123","456")

这个函数定义为thank_you(something, name),形参顺序是something,name,正确的顺序是先"Chinese"后"xqs"。正确的实参传递是,第一个是You help me with Chinese . xqs;第二个是You help me with xqs . Chinese;

  1. 关键字参数
    由于形参顺序太难处理,我们就可以使用关键字参数方法。关键字参数方法是传递给函数一对------"形参名称-实参",直接将形参和实参关联起来,因此不会出现顺序混淆导致的错误结果,并且能够指出函数调用各个值的意义。
python 复制代码
def thank_you(something, name):
    R = "You help me with " + something + "." + name
    S = "Thank you," + name
    return print(R,S)

thank_you(something="Chinese",name="xqs")
thank_you(name="xqs",something="Chinese")

当我们指定了将 something 赋值为"Chinese",将 name 赋值为"xqs"之后,不论顺序如何,都能够正确地输出结果。

变量的作用域

根据程序中变量所在的位置和作用域,分为局部变量和全局变量。

  1. 局部变量
    局部变量是指在函数内部定义的变量,仅在函数内部有效。
python 复制代码
def thank_you(something, name):
    R = "You help me with " + something + "." + name
    S = "Thank you," + name
    return print(R,S)

thank_you(something="Chinese",name="xqs")
thank_you(name="xqs",something="Chinese")
print(R)

我们在函数外部使用函数内部变量 R 的时候,会提示 R 没有定义,即不存在。

  1. 全局变量
    全局变量是指在函数外部定义的变量,在整个程序中有效。若要在函数内部使用全局变量,则分为两种情况:一是单纯引用,则不需要任何操作;二是需要在函数内部修改全局变量,则需要提前使用保留字 global 声明。

返回值

函数没有返回值,因此打印输出的结果为 None

函数加上了 return 返回了立方值,因此打印输出结果为 8。

代码复用

  1. 简单的代码复用
    编写函数称为封装,执行函数称为调用,代码复用即将封装起来的函数进行调用。
python 复制代码
def text(x):
    a = x**3
    print(a)

def thank_you(something, name):
    R = "You help me with " + something + "." + name
    S = "Thank you," + name
    return print(R,S)

text(2)
thank_you(something="2的立方值",name="xqs")

text(5)
thank_you(name="xqs",something="5的立方值")

先封装两个函数,然后分别进行调用。

  1. 将函数储存在模块
    将函数储存在模块中,再将模块导入主程序。通过将函数储存在独立文件中,可以把重点放在程序的更高层逻辑上。还能帮助我们在其他程序编写中使用此函数,还可以将此函数分享给其他程序员,同样地还可以使用其他程序员编写的函数库。

首先创建模块,模块是扩展名为.py 的文件,其中为封装好的函数。xqs.py 即为模块我们创建的摸块。

(1) 导入整个模块

当我们导入整个模块之后,那么模块包含的函数就可以使用了。

在同一个文件夹下创建了一个求立方和表示感谢的 py 文件,在这个文件中导入刚才创建的模块,再进行函数调用,可以发现这些代码运行正确。这种导入整个模块再进行函数调用的方法总结为:

(2) 导入指定函数

如果整个模块有许多函数,而我们只需要其中的一、两个函数,那么我们可以指定函数名进行特定导入。这种导入指定函数的方法总结为:

(3) 使用 as 给模块指定别名

我们的模块名为"xqs",稍显冗长。我们可以给他指定一个缩写名,方便使用,可以得到一样的运行结果。这种以别名导入模块的方法总结为:

(4) 使用 as 给函数指定别名

我们的函数名为"thank_you",稍显冗长。我们可以给他指定一个缩写名,方便使用。

(5) 导入模块中的所有函数

使用(*)符号可以导入模块中的所有函数,如果模块不是自己写的,由于函数名很可能会重复,所以出现一些意想不到的结果。导入模块中的所有函数的方法总结为:

综上,代码复用最为推荐以上的第(3)种方式------使用 as 给模块指定别名,这样会减少出错概率,并且使代码更为清晰、更加容易阅读和理解。

类就是对象的抽象式汇总,基于类创建对象的时候,每个对象都具有类的通用属性,在获得通用属性的基础上,可根据需要赋予对象以个性。

创建和使用类

  1. 创建类

现在创建一个表示猫咪的简单类 Cat(习惯上类的命名一般都是开头字母大写)。想象一下猫咪,能联想到的共性是两条信息(名字、胖瘦)和两种动作(舔毛、踩奶),所以我们创建的 Cat 类将包含他们。

Cat类的语法结构:

具体解释:

第 1 行,类的命名应为首字母大写,括号内是空的;

第 2 行,我们对这个类的功能进行了说明;

第 4 行,我们开始在类中编写函数,实际上除了上文中的模块,类是函数的另一种汇总方式,在类中的函数我们称为方法。

显然在这个类中有三种方法,首先是第 4 行的__ini__()方法,然后是第 9 行的舔毛()方法,再是第 13 行的踩奶()方法。其中__ini__()方法是类中特有的默认的方法,每当我们根据 Cat 类创建新实例时,Python 都会自动运行它。注意它的开头末尾各有两个下划线,这是默认约定,能够避免与我们定义的普通函数发生命名冲突。

单独对__ini__()方法进行剖析,在此方法中包含了三个形参:self、name 和身材。首先,形参 self 不可缺失且必须位于参数最前。具体原因不必深究,这么做的目的是可以理解为方便自己引用自己。再之,对于形参 self,我们不需要传递实参。最后,对于后面两个形参,每次创建 Cat 类实例时,都需要给他俩提供实参。

对于另外两个方法:舔毛()和踩奶()。由于这些方法是单独定义的,因此不需要额外的信息,因此只需要一个形参 self。在这里,舔毛()和踩奶()只是打印一条信息说明猫咪是在作出行为,但是随着学习我们可以编写一个动画真正实现。

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")
  1. 实例化

接下来将 Cat 类实例化,即创建一个表示特定猫咪的实例,它的名字叫咪咪,身材属性是胖。

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")

my_cat = Cat("咪咪","胖")

(1)访问属性

self.name 和 self.身材是 Cat 类中的属性,舔毛()和踩奶()是 Cat类中的方法。访问属性时采用句点表示法:

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")

my_cat = Cat("咪咪","胖")

print("My cat's name is " + my_cat.name + ".")
print("我的小猫咪身材" + my_cat.身材 + "。")

(2)调用方法

调用方法时,也采用句点表示法:

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")

my_cat = Cat("咪咪","胖")

my_cat.舔毛()
my_cat.踩奶()

(3)创建多个实例

我们可根据需求创建其他的实例,比如你也有一只猫,那我也可以把你的猫实例化。

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")

my_cat = Cat("咪咪","胖")
print("My cat's name is" + my_cat.name + ".")
print("我的小猫咪身材" + my_cat.身材 + "。")
my_cat.踩奶()

your_cat = Cat("喵喵","瘦")
print("My cat's name is" + my_cat.name + ".")
print("我的小猫咪身材" + my_cat.身材 + "。")
your_cat.舔毛()

继承

  1. 继承父类

如果要编写的类是另一个已经编号的类的特殊版本,那么就可以使用继承。类 a 继承另一个类 A 的时候,将自动获得类 A 的所有属性和方法;原有的类 A 成为父类,新类 a 成为子类。子类除了继承其父类的所有属性和方法之外,还可以定义自己的属性和方法。
例如,模拟英短猫这个品种的猫咪,我们可以在前面创建的 Cat 类基础上创建新类 EdCat,只需要为英短猫特有的属性和行为编写代码。具体来说,EdCat 子类的创建首要完成任务是获得父类 Cat 类的属性,因此需要如下结构形式:首先是 Cat 类代码。创建子类时,父类必须包含在当前文件中,且位于子类前面。接着开始定义子类 EdCat(),括号中必须包含父类名。__init__方法中接受创建 Cat 实例所需信息,super()是一个能够将父类和子类关联的特殊函数,完成继承。

为了测试继承是否成功,创建了my_edcat英短猫my_edcat并输出其身材,发现其与猫咪信息相同,具备猫咪的属性,所以继承成功。

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")

class EdCat(Cat):
    def __init__ (self,name,身材):
        super().__init__(name,身材)

my_edcat = EdCat("咪咪","胖")
print(my_edcat.身材)
  1. 子类定义新属性和方法

子类继承了父类属性之后,可添加一些子类特有的新属性和方法。

以英短猫为例,添加新属性以及一个相关联的方法。新属性为英短猫特点以及描述特点的方法。

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")

class EdCat(Cat):
    def __init__ (self,name,身材):
        super().__init__(name,身材)
        self.英短特点 = "圆脸尖耳,好奇心强,与人亲近"

    def 描述_英短特点(self):
        print("英短猫的特点是:" + self.英短特点 + "。")

my_edcat = EdCat("咪咪","胖")
my_edcat.描述_英短特点()

代码注释:

第 15 行是新属性,第 17 行是与新属性相关联的新方法,第 21 行是调用新方法,运行结果说明新属性和新方法定义成功。如果有需要还可以添加其他新属性与方法,来更加清晰地定义英短猫的类,Python 并无限制。

  1. 重写父类方法

某些父类方法可能不符合子类的特性,我们可以对其进行重写。只要在子类中定义一个与父类重名的方法,Python 在运行时将不会考虑父类方法,而直接选择子类定义的相应方法作为运行对象。

比如 Cat()类中有一个踩奶()的方法,对于英短来说,没有瘦的,都是胖圆健硕的,所以要重写方法。

python 复制代码
class Cat():
    def __init__(self, name, 身材):
        self.name = name
        self.身材 = 身材

    def 舔毛(self):
        print(self.name + "正在舔毛")

    def 踩奶(self):
        print(self.name + "正在踩奶")

class EdCat(Cat):
    def __init__ (self,name,身材):
        super().__init__(name,身材)
        self.英短特点 = "圆脸尖耳,好奇心强,与人亲近"

    def 描述_英短特点(self):
        print("英短猫的特点是:" + self.英短特点 + "。")

    def 踩奶(self):
        print(self.name + "英短踩奶")

my_edcat = EdCat("咪咪","胖")
my_edcat.踩奶()

导入类

为了让代码尽可能实现这个理念,python 允许将类存储在模块中,在主程序中导入所需模块简化代码。上一小节讲了函数可以存储在模块中简化代码,这一节将讲述将类存储在模块中简化代码。

  1. 导入单个类
    (1) 创建包含单个类的模块

首先创建一个只包含 Cat()类的模块,代码与之前的 Cat()类完全相同,区别只是我们将其存储在 cat.py 的模块中。

(2) 导入单个类

紧接着我们导入 Cat()类并将其实例化,用 from <模块名> import <类名> 语句打开模块 cat 并导入其中的 Cat()类。

PS:如果这个 my_cat.py 文件中包含了整个 Cat 类,它的长度像之前所展示的,非常之长。但是通过将类转移到模块中,编写代码时,导入该模块,就可以使用其所有功能,主程序代码将会整洁易读。从代码编写过程中的逻辑思维来讲,底层逻辑将会被储存在模块这种独立文件中,我们就能够专注于更高层的逻辑。

python 复制代码
import cat
my_cat = cat.Cat("咪咪","胖胖")
my_cat.踩奶()
print("\n")
my_edcat = cat.EdCat("哈哈","健硕")
my_edcat.踩奶()
  1. 导入多个类
    (1) 创建包含多个类的模块

首先创建一个包含 Cat()类和 EdCat()类的模块,既可以模拟猫,也可以模拟英短猫。代码与之前的 Cat()类和 EdCat()类完全相同,区别只是我们将其存储在cat.py 的模块中。

(2) 导入多个类

我们要在同一个程序中创建猫咪和英短猫咪,因此我们同事导入 Cat()和EdCat()两个类,导入相应的类之后,就可以根据需要创建任意数量的实例,在这个示例中,我们创建了一只叫咪咪的小猫咪和一只叫哈哈的英短猫咪。

python 复制代码
from cat import Cat, EdCat

my_cat= Cat("咪咪","胖胖")
print("My cat's name is " + my_cat.name + ".")
print("我的小猫咪身村" + my_cat.身材 + "的。")
my_cat.踩奶()

print("\n")

my_edcat = EdCat("哈哈","健硕")
print("我的英短的名字是" + my_edcat.name + "。")
my_edcat.踩奶()
my_edcat.描述_英短特点()
  1. 导入整个模块
    (1)导入整个模块

导入整个模块之后,使用句点表示法访问需要的类。

python 复制代码
import cat
my_cat = cat.Cat("咪咪","胖胖")
my_cat.踩奶()
print("\n")
my_edcat = cat.EdCat("哈哈","健硕")
my_edcat.踩奶()

(2)导入模块中的所有类

与之前的导入模块中的所有函数相同,使用语法为:

这种方式不推荐,因此不列举具体示例。

不推荐的原因有两点:一是不能清除地知道程序使用了哪些类,二是有可能会出现相同命名的名称。

模块与库

概念

  1. 模块
    模块即一组函数或者一组类,它的作用是将函数或者类成组地保存为独立文件,方便我们更专注于程序编写的更高层逻辑。

  2. 库即一组模块,它的作用是将模块成组地保存为独立文件,方便我们更专注于程序编写的更更高层逻辑。

前面 4 讲所学的普通程序语句是最底层,后面的函数和类算是平级(但是类中可以包含多个方法,类中方法即函数),类稍大一级,都归于中层,再后面的模块是高层,最后是超高层------库。

标准库

库分为标准库和第三方库,标准库是 Python 内置的,无需安装;第三方库则是由国内外大神自己开发的开源使用的库,需要安装。

  1. turtle 库
    turtle(海龟)是一个能够进行图形绘制的库,它的绘制概念非常直观------turtle 小海龟在笛卡尔直角坐标系中爬行,其爬行轨迹形成了图形。小海龟最初位于坐标系原点(0, 0),前进方向为 X 轴正向,小海龟有有"前进"、"旋转"、"后退"等爬行操作,如,输入以下代码,"小海龟"正在向前爬 1000个像素。
python 复制代码
import turtle
turtle.forward(1000)

下面介绍一道 Python 二级真题,让我们来看看具体如何考察?

考生文件夹下存在一个文件 PY201.py,请写代码替换横线,不修改其他代码,实现以下功能:【10 分】

使用turtle库的turt1e.right()函数和turt1e.fd()函数绘制一个正方形,

边长为 200 像素,效果如图所示。

python 复制代码
import turtle

#方法一
d = 0
for i in range(4):
    turtle.fd(200)
    d += 90
    turtle.seth(d)

#方法二
for i in range(1,5):
    turtle.fd(200)
    turtle.seth(90*i)

#方法三
for i in range(4):
    turtle.fd(200)
    turtle.seth(90)

turtle.fd()是前进函数,turtle.seth()函数可以改变海龟的行进方向(角度按逆时针)。方法二是一个 for 循环,不做过多解释;方法三中turtle.left()函数也可以改变海龟的行进方向(角度按逆时针)。

  1. random 库
    Python 提供的 random 库可用于产生各种分布的伪随机数序列。在random 库中,最基本的函数random.random(),它能够胜出一个[0.0, 1.0)之间的随机小数。

    下面是一道 Python 二级真题,让我们来看看具体如何考察?
    考生文件夹下存在一个文件 PY103.py,请写代码替换横线,不修改其他代码,题目要求如图 5.36,实现以下功能:【5 分】
  • 以 123 为随机数种子,随机生成 10 个在 1(含)到 999(含)之间的随机数,每个随机数后跟随一个逗号进行分隔,屏幕输出这 10 个随机数
  • random.seed()是产生随机数种子的函数,random.randint()函数可以在某个数字范围内产生随机数,end 参数可以在每个输出结果后面进行逗号分隔。

第三方库

从 Python 实用性角度来讲,随着我们对 Python 的理解更深、应用更广,肯定会安装各种各样的第三方库,这些库都是大神免费开发并提供给我们使用的宝贵财富。比如我们在处理 Excel 表格时,会用到 openpyxl 库、xlsxwriter 库、数据处理库 numpy 和 pandas、包括画图库 matplotlib;在开发网站时,会用到 Django库;在编写爬虫时,会用到 Scrapy 库、requests 库、re 库;在科学数据处理时,会用到 scipy 库等等。

  1. 下载并安装(pip)
    如同 Python 编程之前需要安装 Python 编译器一样,使用第三方库之前首先要进行第三方库的下载与安装。在此仅提供一种最为简便、实用、好用的方法,即 pip 安装,使用方法是使用 win+R 键或者在开始菜单右键打开运行对话框,输入 cmd,打开命令提示符,然后输入一行命令:

    以安装 numpy 库为例
  2. 更换服务器

(1)临时性地更换服务器

这个方法操作非常简便,适用于新手和下载库较少的学习者。在原来 pip install <库名>的基础上加上这么一行:

(2)永久更换服务器

以清华大学服务器为例,介绍如何永久更换,也比较简单,是个一劳永逸的办法,也是三部曲:

(a)进入自己的系统用户名文件夹

(b)创建 pip 文件夹

(c)创建 pip.ini 文件并进行编辑如下内容:


  1. jieba 库

jieba("结巴")库是用于中文文本处理、对文本词语分割的库。

各个领域第三方库的名称进行了解

相关推荐
JUNAI_Strive_ving3 分钟前
番茄小说逆向爬取
javascript·python
一休哥助手4 分钟前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
彤银浦4 分钟前
python学习记录7
python·学习
救救孩子把5 分钟前
深入理解 Java 对象的内存布局
java
DY009J5 分钟前
深度探索Kali Linux的精髓与实践应用
linux·运维·服务器
落落落sss7 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
翔云12345612 分钟前
MVCC(多版本并发控制)
数据库·mysql
万物皆字节13 分钟前
maven指定模块快速打包idea插件Quick Maven Package
java
夜雨翦春韭19 分钟前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
简单.is.good25 分钟前
【测试】接口测试与接口自动化
开发语言·python