PS:这篇文章是以一个学习者的角度来汇总知识点以及教程,对于想学习Python的入门者也会比较友好,想学习python可以先收藏,我会慢慢持续更新。学艺不精,如有纰漏,敬请指正。
目录
3.3.3statistics.median_low() #数据中的低中位数
3.3.4statistics.median_high() #数据中的高中位数
3.3.6statistics.pvariance() #计算数据的总体方差
一、函数
在学习笔记一中学习了python的一些基本知识和基础语句,肯定许多人发现那些方法挺好用的,比如分割字符串,我们没必要去想这个split()是怎么整出来的,反正需要用的时候直接调用这个方法就可以了。
但是python再厉害,也不可能把我们需要用的方法穷尽,就算穷尽,我们也记不住,于是我们可以自己定义方法,再本次程序中使用,写一次,终身质保,岂不美哉。这个就是函数。
举个栗子:比如我们现在需要对三个数A,B,C进行操作,需要先把A和B相加,再把结果乘C,即(A+B)*C,我们就可以自己写一个函数,ABC就是函数的参数,来实现这个功能。接下来如果我们需要算(M+N)*Z,我们直接调用这个函数,只需要把ABC换成MNZ就可以了,不需要再写一遍这个又加又乘的代码。
简单点说函数就是一段实现特定功能的代码,使用函数可以提高代码的重复利用率。
Python 使用 def 关键字来声明函数,格式如下所示:
def 函数名(参数):
函数体
return 返回值
当我们不确定参数的个数时,可以使用不定长参数,在参数名前加 *
进行声明。
举例如下:
第一个函数的作用就是传入姓名参数,输出Hello姓名。比如Hello World。
第二个函数就是刚才的例子,s是用来暂存结果,作为返回值,以便其他的函数调用这个计算结果。
第三个即不定长参数的例子。
# 无返回值
def my_print(name):
print('Hello', name)
# 有返回值
def my_sum(A, B, C):
s = (A + B)*C
return s
print(s)
# 不定长参数
def my_variable(*params):
for p in params:
print(p)
调用一个函数只需要知道函数名和参数即可。
my_print('World')
result = my_sum(1, 2, 3)
print(result)
#输出结果
Hello World
9
1.1函数值传递与引用传递
当在定义函数时都会选择有参数的函数形式,函数参数的作用是传递数据给函数,令其对接收的数据做具体的操作处理。参数分为形参和实参。
形式参数:在定义函数时,函数名后面括号中的参数就是形式参数。
实际参数:在调用函数时,函数名后面括号中的参数称为实际参数,也就是函数的调用者给函数的参数(八股文同学和考试同学可以背一下,开发人员不用)。
可能一些初学者听到这里已经开始头疼了。(这块稍微难理解一些我们开始经典的举栗子环节)
简单解释就是一个演员参演一部电视剧,男主角,形参就是他在居中演的角色。别人喊他都会喊剧中的名字。实参就是他本人实际的名字。
接下来说值传递和引用传递,值传递和引用传递的区别是,函数参数进行值传递后,若形参的值发生改变,不会影响实参的值;而函数参数继续引用传递后,改变形参的值,实参的值也会一同改变。
其实就是演员化妆和被动整容。值传递就是演员出演一个剧,他需要戴假发,化妆,甚至女扮男装。但他本人并没有发生改变,演出结束,他还是他。
引用传递。演员出演一个剧,需要在脸上画个疤,但是不小心发生了意外,导致脸上真的留了一个疤,那么即使他演出结束,这个疤也还在脸上,剧中演员脸发生了改变,实际这个演员也发生了改变,这就是引用传递。
值传递:适用于实参类型为不可变类型(字符串、数字、元组),引用(地址)传递:适用于实参类型为可变类型(列表,字典);
def demo(mo) :
mo += mo
print("形参值为:",mo)
print("-------值传递-----")
a = "csdn"
print("a的值为:",a)
demo(a)
print("实参值为:",a)
print("-----引用传递-----")
a = [1,2,3]
print("a的值为:",a)
demo(a)
print("实参值为:",a)
#输出结果
-------值传递-----
a的值为: csdn
形参值为: csdncsdn
实参值为: csdn
-----引用传递-----
a的值为: [1, 2, 3]
形参值为: [1, 2, 3, 1, 2, 3]
实参值为: [1, 2, 3, 1, 2, 3]
1.2 匿名函数
对于定义一个简单的函数,Python 还提供了另外一种方法,即 lambda 匿名函数。
常用来表示内部仅包含 1 行表达式的函数。如果一个函数的函数体仅有 1 行表达式,则该函数就可以用 lambda 表达式来代替。
(听着匿名函数多么高大上是吧,其实就是简单函数的简单写法,没什么大不了的)
比如我们需要写一个求两个数和的函数。那么正常写应该是这样的。
def add(x, y):
return x + y
print(add(3,4))
#输出结果
7
那么我们高大上的匿名函数怎么写呢
add = lambda x,y:x+y
print(add(3,4))
#输出结果
7
这么一对比就明白了吧,接下来我们介绍一下匿名函数的语法格式:
name = lambda [list] : 表达式
那么 匿名函数有什么好处呢?(八股文同学和考试同学可以记一下,同学:听我说谢谢你......)
1.对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁;
2.对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。
二、模块和包
2.1模块和包时什么
在Python中,模块(Module)一般是单个python文件;包(package)由分层模块(Module)构成——相关目录里的模块构成。Python中的库(library)是参考其它编程语言的说法,既可以是一个模块也可以是一个包,换言之是对模块或包的通俗的说法。
模块里面定义了一些函数、类、变量等。模块的名字就是该文件的名字,一般情况下,是一个以.py为后缀的文件。
包(package)是多个模块的聚合体形成的文件夹,里面可以是多个py文件,也可以嵌套文件夹。
Python 有很多自带的模块(标准库)和第三方模块,一个模块可以被其他模块引用,实现了代码的复用性。
2.2怎么引用模块和包
从包中引入模块有如下两种方式:
1.import ...
import 包名1.包名2...模块名
2.from ... import ...
from 包名1.包名2... import 模块名
from 包名1.包名2...模块名 import 变量名/函数名
现在我们创建一个a模块,即a.py
# a 模块中引入 b 模块
#这里pg1就是包,里面包含b.py文件,即b模块。
import pg1.b
from pg1 import b
# a 模块中引入 c 模块
#同理
import pg2.c
from pg2 import c
# a 模块中引入 c 模块和 d 模块
import pg2.c,pg2.d
from pg2 import c,d
# a 模块中引入包 pg2 下的所有模块
from pg2 import *
# a 模块中引入 d 模块中函数 d()
#先从pg2包中引入模块d,在调用模块d的函数。
from pg2.d import d
# 调用函数 d()
d()
调用其他模块的函数要保持先引入,再调用的原则,就像你去借别人家的东西,你肯定要先跟人家说一声,然后再拿,不然就叫偷了。
2.3_init_.py文件又是什么
包是存放模块的文件夹,包中包含 __init__.py
和其他模块。所有的包都是模块,所有的模块不一定是包,包只是一种特殊的模块,任何具有 __path__
属性的模块都会被当作是包。(这一块稍微硬核一点,老规矩,看不懂不要为难自己,了解后即可跳过,以后边用边理解也会明白的)
解释一下什么是__init__.py,根据上面的描述,我们知道包里面包含一些模块,也可以包含其他包。于是我们
在PyCharm创建项目Demo01,比如这个:
./
├─ Demopy2.py
├─ Demo01.py
└─ Demopy1
└─ __init__.py
Demo01.py
是项目Demo01唯一的入口文件,就是运行项目从这个文件开始。 目录Demopy1
是一个包,而Demopy2.py
是一个模块。
我们在Demo01.py中写代码测试一下这个结论:
import Demopy1
import Demopy2
if __name__ == "__main__":
print("Demopy1.{}".format(Demopy1.__path__))
print("Demopy2.{}".format(Demopy2.__path__))
#运行结果
AttributeError: module 'Demopy2' has no attribute '__path__'.
Did you mean: '__name__'?
Demopy2.py没有被识别为一个包,而是一个模块。
此时__init__.py
、 Demopy2.py
都是空文件 ,那Demopy1和Demopy2区别是什么,其实就是一个有__init__.py,是包,没__init__.py,是模块。__init__.py
文件的主要作用是初始化包。当导入一个包时,Python 解释器会首先执行该包下的 __init__.py
文件。我们可以在 __init__.py
文件中执行一些初始化操作,例如设置包的全局变量、导入特定模块或子包等。也可以什么也不做。
当然以上的讨论只限于常规包,这是python3.2以前的规定,从python3.3开始,Python 引入了 命名空间包 的概念。命名空间包是不同文件集的复合,每个文件集给父包贡献一个子包,所有的包中都不需要包含 __init__.py 文件。
三、数学模块
Python 中又许多与数学相关模块,如下所示:
模块 | 描述 |
---|---|
math | 提供了对 C 标准定义的数学函数的访问(不适用于复数) |
cmath | 提供了一些关于复数的数学函数 |
decimal | 为快速正确舍入的十进制浮点运算提供支持 |
fractions | 为分数运算提供支持 |
random | 实现各种分布的伪随机数生成器 |
statistics | 提供了用于计算数字数据的数理统计量的函数 |
我么常用的有math,random, statistics模块。
3.1 math模块
大家还记得dir()吗?在第一章笔记中介绍的有,dir() 函数用来列出某个类或者某个模块中的全部内容。
import math
dir(math)
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh',
'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh',
'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor',
'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite',
'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf',
'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau',
'trunc']
接下来介绍一些常用的数学函数(了解即可,用的时候再查)
3.1.1ceil(x)/floor(x)
ceil(x)返回 x 的上限,即大于或者等于 x 的最小整数,floor(x)返回 x 的向下取整,小于或等于 x 的最大整数。
import math
x = -1.5
print(math.ceil(x))
print(math.floor(x))
#输入结果
-1
-2
3.1.2fabs(x)
返回 x 的绝对值(这个很好理解)
3.1.3fmod(x, y)
返回 x/y 的余数,值为浮点数
import math
x = 3
y = 2
print(math.fmod(x, y))
#输出结果
3.1.4factorial(x)
返回 x 的阶乘,如果 x 不是整数或为负数时则将报错。
3.1.5pow(x, y)
返回 x 的 y 次幂。
3.1.6fsum(iterable)
返回迭代器中所有元素的和。
import math
print(math.fsum((1, 2, 3, 4, 5)))
#输出结果
15
3.1.7sqrt(x)
返回 x 的平方根。
3.1.8trunc(x)
返回 x 的整数部分。
3.1.9常量
import math
# 常量 e
print(math.e)
# 常量 π
print(math.pi)
3.2random 模块
import random
print(random.randint(1, 100))
random 模块可以生成随机数。介绍一些常用函数。
3.2.1random()
返回 [0.0, 1.0) 范围内的一个随机浮点数。
import random
print(random.random())
#输出结果
0.6254264518542579
3.2.2uniform(a, b)
返回 [a, b) 范围内的一个随机浮点数。
import random
print(random.uniform(1.1, 9.9))
#输出结果
5.1241663858954125
3.2.3randint(a, b)
返回 [a, b] 范围内的一个随机整数(可以用来做验证码)。
import random
print(random.randint(1, 100))
#输出结果
54
3.2.4choice(seq)
从非空序列 seq 返回一个随机元素。
import random
print(random.choice('123456'))
#输出结果
4
3.2.5shuffle(x[, random])
将序列 x 随机打乱位置。
import random
l = [1, 2, 3, 4, 5, 6]
random.shuffle(l)
print(l)
#输出结果
[5, 4, 6, 1, 2, 3]
3.3 statistics模块
3.3.1statistics.mean()
求算术平均值
import statistics
date = [1,2,98,99]
statistics.mean(date)
#输出结果
50
3.3.2statistics.median()
计算数据的中位数,如果有两个中位数,则返回其平均值
import statistics
date = [11,12,13,14,15,16]
statistics.median(date)
#输出结果
13.5
3.3.3statistics.median_low() #数据中的低中位数
import statistics
date = [11,12,13,14,15,16]
statistics.median_low(date)
#输出结果
13
3.3.4statistics.median_high() #数据中的高中位数
import statistics
date = [11,12,13,14,15,16]
statistics.median_high(date)
#输出结果
14
3.3.5statistics.mode() #计算众数
import statistics
date = [1,2,2,3,3,3]
statistics.mode(date)
#输出结果
3
3.3.6statistics.pvariance() #计算数据的总体方差
import statistics
date = [11,12,13,14,15,16]
statistics.pvariance(date)
#输出结果
2.9166666666666665