1 入门基础

1.1 标识符

标识符是编程时使用的名字,用于给变量、函数、语句块等命名,Python 中标识符由字母、数字、下划线组成,不能以数字开头,区分大小写。

以下划线开头的标识符有特殊含义,单下划线开头的标识符,如:

  • _xxx ,表示不能直接访问的类属性,需通过类提供的接口进行访问,不能用 from xxx import * 导入;
  • 双下划线开头的标识符,如:__xx,表示私有成员;
  • 双下划线开头和结尾的标识符,如:__xx__,表示 Python 中内置标识,如:__init__() 表示类的构造函数。

1.2 关键字

关键字表
and exec not assert finally or
break for pass class from print
continue global raise def if return
del import try elif in while
else is with except lambda yield

上面表中是 Python 中的关键字(保留字),我们在自定义标识符时不能使用关键字。

1.3 数据类型

  • 整数:可以为任意大小、包含负数

  • 浮点数:就是小数

  • 字符串:以单引号 '、双引号"、三引号 '''"""括起来的文本

引号的开始与结束须类型相同,三引号可以由多行组成。如下所示:

1
2
3
4
5
6
7
8
id = '001'

name = "张飞"

skill = '''
咆哮
替身'''

  • 布尔:只有 TrueFalse 两种值

  • 空值:用 None 表示

  • 变量:是可变的

  • 常量:不可变

1.4 输入输出

Python 输出使用 print(),内容加在括号中即可。如下所示:

1
print('Hello Python')

Python 提供了一个 input(),可以让用户输入字符串,并存放到一个变量里。如下所示:

1
2
name = input()
print('Hi',name)

1.5 运算符

常用运算符

运算符 描述 示例
+ 相加 a + b
- 相减 a - b
* 相乘 a * b
/ 相除 a / b
% 取模 a % b
** a**b 表示 a 的 b 次幂
// 取整除 9 // 4 结果为 2
== 是否相等 a == b
!= 是否不等于 a != b
> 是否大于 a > b
>= 是否大于等于 a >= b
<= 是否小于等于 a <= b
= 简单的赋值运算符 a = b + c
+= 加法赋值运算符 a += b 等效于 a = a + b
-= 减法赋值运算符 a -= b 等效于 a = a - b
*= 乘法赋值运算符 a *= b 等效于 a = a * b
/= 除法赋值运算符 a /= b 等效于 a = a / b
%= 取模赋值运算符 a %= b 等效于 a = a % b
**= 幂赋值运算符 a **= b 等效于 a = a ** b
//= 取整除赋值运算符 a //= b 等效于 a = a // b
& a & b
a 丨 b
^ 异或 a ^ b
~ 取反 ~a
<< 左移动 a << 3
>> 右移动 a >> 3
and 布尔类型与 a and b
or 布尔类型或 a or b
not 布尔类型非 not a
is 判断两个标识符是否引用同一个对象 a is b
is not 判断两个标识符是否引用不同对象 a is not b

运算符优先级

运算符 描述(由上至下对应优先级由高到低)
** 幂运算
~ + - 取反、正号、负号
* / % // 乘、除、取模、取整除
+ - 加法、减法
>> << 右移、左移
&
^ 丨 异或、或
<= < > >= 比较运算符
== != 是否等于、是否不等于
= %= /= //= -= += *= **= 赋值运算符
is is not 身份运算符
in not in 成员运算符
not and or 逻辑运算符

1.6 缩进

Python 不使用 {} 来控制类、函数、逻辑判断等,而是使用缩进,缩进的空格可变。如下所示:

1
2
3
4
if True:
print(True)
else:
print(False)

1.7 多行

Python 中一般以新行作为语句的结束标识,可以使用 \ 将一行语句分为多行显示。如下所示:

1
2
3
4
5
6
a = 128
b = 1024
c = 512
d = a + \
b - \
c

如果包含在 []{}() 括号中,则不需要使用 \。如下所示:

1
2
3
4
5
arr = {
a,
b,
c
}

1.8 注释

Python 中单行注释使用 #,多行注释使用三个单引号(''')或三个双引号(""")。如下所示:

1
2
3
4
5
6
# 我是单行注释

'''
我是多行注释
我是多行注释
'''

___________

2 基本语句

2.1 条件语句

在进行逻辑判断时,我们需要用到条件语句,Python 提供了 ifelifelse 来进行逻辑判断。格式如下所示:

1
2
3
4
5
6
7
8
if 判断条件1:
执行语句1...
elif 判断条件2:
执行语句2...
elif 判断条件3:
执行语句3...
else:
执行语句4...

2.2 循环语句

当需要多次重复执行时,我们要用到循环语句,Python 提供了 for 循环和 while 循环。

2.2.1 for循环

for 循环可以遍历任何序列,比如:字符串。如下所示:

1
2
3
str = 'Python'
for s in str:
print(s)

输出结果:

1
2
3
4
5
6
P
y
t
h
o
n

如果你对for循环很感兴趣,可以尝试一下下面这个有意思的小程序。

1
2
3
4
import time
for i in range(11):
print("\r倒计时%d"%(10-i),end="")
time.sleep(1)

2.2.2 while循环

while 循环,满足条件时进行循环,不满足条件时退出循环。如下所示:

1
2
3
4
5
6
sum = 0
m = 10
while m > 0:
sum = sum + m
m = m - 1
print(sum)

输出结果:

1
55

2.2.3 break

break 用在 for 循环和 while 循环语句中,用来终止整个循环。如下所示:

1
2
3
4
5
str = 'Python'
for s in str:
if s == 'o':
break
print(s)

输出结果:

1
2
3
4
P
y
t
h

2.2.4 continue

continue 用在 for 循环和 while 循环语句中,用来终止本次循环。如下所示:

1
2
3
4
5
str = 'Python'
for s in str:
if s == 'o':
continue
print(s)

输出结果:

1
2
3
4
5
P
y
t
h
n

2.3 空语句

pass 是空语句,它不做任何事情,一般用做占位语句,作用是保持程序结构的完整性。如下所示:

1
2
if True:
pass

___________

3 数据类型

3.1 数值

3.1.1 数值类型

Python有三种数值类型,分别是:整型(int)、浮点型(float)、复数(complex),在低版本Python2中,还包含长整型(long)。

  • 整型:包括正整数、负整数。如:1024、-1024。整型有四种进制表示,分别为:二进制、八进制、十进制、十六进制,说明如下表所示:
种类 描述 引导符
二进制 由 0 和 1 组成 0b 或 0B
八进制 由 0 到 7 组成 0o 或 0O
十进制 默认情况
十六进制 由 0 到 9、a 到 f、A 到 F 组成,不区分大小写 0x 或 0X
  • 浮点型:由整数部分和小数部分组成。

  • 复数:由实数部分和虚数部分组成。

  • 分数:需要载入Fraction模块,如:

1
2
3
4
5
from fractions import Fraction  
tt = Fraction(1,3)
print(tt/4)
print(tt*3)
print(2**(tt))

结果输出:

1
2
3
1/12
1
1.2599210498948732

3.1.2 基本运算

我的基本运算见下表,整型和浮点型均支持下表中运算。

运算 描述
x + y x 和 y 的和
x - y x 和 y 的差
x * y x 和 y 的乘积
x / y x 和 y 的商
x // y x 除以 y,取整除
x % y x 除以 y,取模
-x x 取反
+x x 不变
abs(x) x 的绝对值
int(x) 将 x 转换为整数
float(x) 将 x 转换为浮点数
complex(x, y) 一个带有实部 x 和虚部 y 的复数,y 默认为 0。
divmod(x, y) (x // y, x % y)
pow(x, y) x 的 y 次幂
x ** y x 的 y 次幂

3.1.3 数学函数

除了上面的基本运算外,我还可以借助数学模块 math 实现更多的运算。首先要先引入数学模块 math。如下所示:

1
import math

引入之后就可以使用了,以 math 模块中求平方根函数 sqrt(x)  为例。使用方式如下所示:

1
2
import math
math.sqrt(1024)

math 模块中除了求平方根函数,还有很多可以使用的函数。如下表所示:

函数 描述
abs(x) 返回 x 的绝对值
ceil(x) 返回 x 的上入整数,如:math.ceil(1.1) 返回 2
floor(x) 返回 x 的下舍整数,如:math.floor(1.1) 返回 1
exp(x) 返回 e 的 x 次幂
log(x) 返回以 e 为底 x 的对数
log10(x) 返回以 10 为底 x 的对数
pow(x, y) 返回 x 的 y 次幂
sqrt(x) 返回 x 的平方根
factorial(x) 返回 x 的阶乘

3.1.4 随机函数

在安全领域有时会用到随机数,random 模块对随机数的生成提供了支持。首先还是要引入 random 模块。如下所示:

1
import random

下面简单介绍两个函数:random(x)函数随机生成一个 0 到 1 范围内的实数。使用如下所示:

1
2
import random
random.random()

uniform(x, y)函数随机生成一个 x 到 y 范围内的实数。使用如下所示:

1
2
import random
random.uniform(1,10)

3.2 字符串

字符串是 Python 的一种数据类型,它可以通过单引号 ‘、双引号 "、三引号 ‘’’ 或 “”" 来定义,本节我们将展开介绍。

3.2.1 访问操作

访问单个字符可以将字符串视为数组

1
2
3
s = 'Python'
# 访问第一个字符 P
print(s[0])

访问范围内字符用:来连接首位指针

1
2
3
4
5
6
7
s = 'Python'
# 访问 yt
print(s[1:3])
# 访问 Pyt
print(s[:3])
# 访问 hon
print(s[3:])

3.2.2 查询编码

Python 使用了 ord() 函数返回单个字符的ASCII码,chr() 函数把编码转成相应字符。如:

1
2
3
s = 'A'
print(ord(s))
print(chr(65))

输出结果:

1
2
65
A

3.2.3 转义符

之前我们说过可以通过反斜杠 \ 将一行语句分多行显示,其实就是 \ 来转义字符,一些常见的转义字符如下表所示:

转义字符 描述
\ 在行尾使用时,用作续行符
\b 退格(Backspace)
\000
\n 换行
\v 纵向制表符
\t 横向制表符
\r 回车

3.2.4 运算符

之前我们已经介绍了大部分运算符,下面再来详细看一下字符串运算符。如下表所示:

运算符 描述
+ 连接符
* 重复输出
[] 通过索引获取字符串中字符
[ : ] 获取字符串中的一部分
in 字符串中是否包含指定字符
not in 字符串中是否不包含指定字符
r/R 字符串原样输出

使用示例如下所示:

1
2
3
4
5
6
7
8
9
s1 = 'Hello'
s2 = 'Python'
print('s1 + s2 -->', s1 + s2)
print('s1 * 2 -->', s1 * 2)
print('s1[0] -->', s1[0])
print('s1[0:2] -->',s1[0:2])
print('"H" in s1 -->','H' in s1)
print('"H" not in s1 -->','H' not in s1)
print('\\r -->', R'\r')

输出结果:

1
2
3
4
5
6
7
s1 + s2 --> HelloPython
s1 * 2 --> HelloHello
s1[0] --> H
s1[0:2] --> He
"H" in s1 --> True
"H" not in s1 --> False
\r --> \r

3.2.5 格式化输出

当我们需要输出的内容中含有变量时,比如:Hello xxxxxx 为变量,此时便需要一种格式化字符串的方式,Python 使用 % 格式化字符串,常用占位符如下表所示:

占位符 描述
%s 格式化字符串
%d 格式化整数
%f 格式化浮点数

以字符串为例,如下所示:

1
print('Hello %s' % 'Python')

输出结果:

1
Hello Python

我们也可以使用字符串的 format() 方法进行格式化,先看下示例:

1
print('{0} {1}'.format('Hello', 'Python'))

这种方式是用传入的参数依次替换字符串内的占位符{0}、{1} …


___________

4 向量

4.1序列

Python中的序列是一块可存放多个值的连续内存空间,类似于C中的数组,其所有值按一定顺序排列,每个值所在位置都有一个编号,称其为索引,我们可以通过索引访问其对应值。我们上一节说的字符串就是一种典型的序列结构。

4.1.1 索引

序列索引支持非负数和负数,索引为非负数,从 0 开始,由左向右计数如:
图片

索引为负数由右向左计数,从 -1 开始,如:

图片

下面通过一个示例作进一步了解,以字符串为例,如下所示:

1
2
3
4
5
>>>str = '贝蒂小熊,乱世不败'
>>>print('str[3] str[-6] =', str[3], str[-6])
str[3] str[-6] = 熊 熊
>>>print('str[5] str[-4] =', str[5], str[-4])
str[5] str[-4] = 乱 乱

从结果来看,我们使用非负数索引与负数索引得到的结果一致。

4.1.2 切片

切片操作可以访问一定范围内的元素,语法如下所示:sname[start : end : step]

  • sname:表示序列的名称;
  • start:开始索引位置**(包括该位置)**,默认为 0;
  • end:表示切片的结束索引位置**(不包括该位置)**,默认为序列的长度;
  • step:步长。

以字符串为例,如下所示:

1
2
3
4
5
6
7
>>>str = '贝蒂小熊,乱世不败'
>>>print(str[:4])
贝蒂小熊
>>>print(str[5:])
乱世不败
>>>print(str[::2])
贝小,世败

4.1.3 相加

Python支持类型相同的序列使用 + 作相加操作,该操作不会去除重复的元素。以字符串为例,如下所示:

1
2
3
4
>>>str1 = '贝蒂小熊'
>>>str2 = '乱世不败'
>>>print(str1 + str2)
贝蒂小熊乱世不败

4.1.4 相乘

Python中,使用数字 n 乘以一个序列会生成新的序列,内容为原来序列被重复 n 次的结果。以字符串为例,如下所示:

1
2
3
>>>str = '贝蒂小熊n'
>>>print(2 * str)
贝蒂小熊贝蒂小熊

4.1.5查询

Python使用 in 关键字检查某元素是否为序列的成员,语法如下:val in seq

  • val:要检查的元素;
  • seq:指定的序列。

通过一个例子作进一步了解,以字符串为例,如下所示:

1
2
3
4
5
>>>str = '贝蒂小熊,乱世不败'
>>>print('熊' in str,'乱' in str)
True True
>>>print('熊乱' in str)
False

4.1.6 内置函数

函数 描述
len() 计算序列的长度
max() 找出序列中的最大元素
min() 找出序列中的最小元素
list() 将序列转换为列表
str() 将序列转换为字符串
sum() 计算元素的和
sorted() 对元素进行排序
enumerate() 将序列组合为一个索引序列,多用在 for 循环中

简单举几个例子,如下所示:

1
2
3
4
5
6
7
8
9
>>>c = [6,5,4,7,2]
>>>print('len -->', len(c))
len --> 5
>>>print('max -->', max(c))
max --> 7
>>>print('list -->', list(c))
list --> [6, 5, 4, 7, 2]
>>>print('sorted -->', sorted(c))
sorted --> [2, 4, 5, 6, 7]

4.2 列表

Python中没有数组,而是加入了功能更强大的列表(list),列表可以存储任何类型的数据,同一个列表中的数据类型还可以不同;列表是序列结构,可以进行序列结构的基本操作:索引、切片、加、乘、检查成员。

4.2.1 创建

列表中所有元素都放在一个中括号 [] 中,相邻元素之间用逗号 , 分隔,如下所示:

1
>>>l = [1024, 0.618, '贝蒂小熊']

4.2.2 访问

通过索引访问列表中的值,还可以使用 : 截取范围内的元素,如下所示:

1
2
3
4
5
>>>l = [1024, 0.618, '贝蒂小熊']
>>>print(l[0])
1024
>>>print(l[1:])
[0.618, '贝蒂小熊']

4.2.3 更新

修改列表的已有元素可以用直接赋值的方法:

1
2
3
4
>>>l = [1024, 0.618, '贝蒂小熊']
>>>l[2] = '北地枭雄'
>>>print(l)
[1024, 0.618, '北地枭雄']

添加新元素使用 append()函数,如:

1
2
3
4
>>>l = [1024, 0.618, '贝蒂小熊']
>>>l.append('乱世不败')
>>>print(l)
[1024, 0.618, '贝蒂小熊', '乱世不败']

删除列表中元素使用 del函数,如下所示:

1
2
3
4
>>>l = [1024, 0.618, '贝蒂小熊']
>>>del l[1]
>>>print(l)
[1024, '贝蒂小熊']

4.2.4 其他函数

count()统计列表中某个元素出现的次数,使用如下所示:

1
2
3
>>>l = ['d', 'b', 'a', 'f', 'd']
>>>print(l.count('d'))
2

index()查找某个元素在列表中首次出现的位置(即索引),使用如下所示:

1
2
3
>>>l = ['d', 'b', 'a', 'f', 'd']
>>>print(l.index('d'))
0

remove()移除列表中某个值的首次匹配项,使用如下所示:

1
2
3
4
>>>l = ['d', 'b', 'a', 'f', 'd']
>>>l.remove('d')
>>>print(l)
['b', 'a', 'f', 'd']

sort()对列表中元素进行排序,使用如下所示:

1
2
3
>>>l = ['d', 'b', 'a', 'f', 'd']
>>>l.sort()
['a', 'b', 'd', 'd', 'f']

copy()复制列表,使用如下所示:

1
2
3
4
>>>l = ['d', 'b', 'a', 'f', 'd']
>>>lc = l.copy()
>>>print(lc)
['d', 'b', 'a', 'f', 'd']

4.3 元组

元组(tuple)与列表类似,但元组是不可变的,可简单将其看作是不可变的列表,元组常用于保存不可修改的内容。

4.3.1 创建

元组中所有元素都放在一个小括号 () 中,相邻元素之间用逗号 , 分隔,如下所示:

1
>>>t = (1024, 0.5, 'Python')

4.3.2 访问

与访问列表中元素类似,如:

1
2
3
4
5
>>>t = (1024, 0.5, 'Python')
>>>print('t[0] -->', t[0])
t[0] --> 1024
>>>print('t[1:] -->', t[1:])
t[1:] --> (0.5, 'Python')

4.3.3 更新

元组中元素不能被修改,我们要用重新赋值的方式操作,如下所示:

1
2
3
4
>>>t = (1024, 0.5, 'Python')
>>>t = (1024, 0.5, 'Python', 'Hello')
>>>print('t -->', t)
t --> (1024, 0.5, 'Python', 'Hello')

元组中的元素不能被删除,我们只能删除整个元组,如下所示:

1
2
3
4
>>>t = (1024, 0.5, 'Python')
>>>del t
>>>print('t -->', t)
NameError: name 't' is not defined

由于元组实例被删除,所以输出了异常信息。

4.3.4 其他函数

len()计算元组中元素个数,使用如下所示:

1
2
3
>>>t = (1024, 0.5, 'Python')
>>>print('len(t) -->', len(t))
len(t) --> 3

ma\()min()返回元组中元素最大、最小值,使用如下所示:

1
2
3
4
5
>>>t = ('d', 'b', 'a', 'f', 'd')
>>>print('max(t) -->', max(t))
max(t) --> f
>>>print('min(t) -->', min(t))
min(t) --> a

tuple()将列表转换为元组,使用如下所示:

1
2
3
4
>>>l = ['d', 'b', 'a', 'f', 'd']
>>>t = tuple(l)
>>>print('t -->', t)
t --> ('d', 'b', 'a', 'f', 'd')

4.4 字典

Dict是Python的一种数据结构,它的内容都是以键-值(key-value)的方式存在的。Dict拥有良好的查询速度,Dict中的值可以是任意Python对象,多次对一个key赋value,后面的value会把前面的value覆盖。

4.4.1 使用

字典的内容在花括号 {} 内,键-值(key-value)之间用冒号 : 分隔,键值对之间用逗号 , 分隔,比如创建字典 d,如下所示:

1
2
3
4
5
6
7
8
# 方式一
>>>l = [('name', '小明'), ('age', 18)]
>>>d = dict(l)
# 方式二
>>>d = dict(name='小明', age='18')
# 空字典
>>>d = dict()
>>>d = {}

字典中的值通过 key 进行访问,如下所示:

1
2
3
4
5
6
7
>>> d = dict(name='小明', age='18')
>>> d['name']
'小明'

# 使用 get 方法
>>> d.get('name')
'小明'

4.4.2 更新

修改操作,以修改 age 为例,如下所示:

1
2
3
4
>>> d = dict(name='小明', age='18')
>>> d['age'] = '20'
>>> d['age']
'20'

清空集合,如下所示:

1
2
3
4
>>> d = dict(name='小明', age='18')
>>> d.clear()
>>> d
{}

4.4.3 其他函数

获取字典的长度,如下所示:

1
2
3
>>> d = dict(name='小明', age='18')
>>> len(d)
2

4.5 集合

集合(set)与字典相同均存储 key,但也只存储 key,因 key 不可重复,所以 set 的中的值不可重复,也是无序的。

4.5.1 使用

集合使用花括号 {} 或者 set() 函数创建,如果创建空集合只能使用 set() 函数,以创建集合 s 为例,如下所示:

1
2
3
4
5
>>>s = {'a', 'b', 'c'}
# 使用 set 函数
>>>s = set(['a', 'b', 'c'])
# 空集合
>>>s = set()

集合中重复的元素会被自动过滤掉,如下所示:

1
2
3
>>> s = {'a', 'a', 'b', 'c', 'c'}
>>> s
{'a', 'c', 'b'}

4.5.2 更新

添加元素可以使用 addupdate 方法,如果元素已经存在,则不进行操作,如下所示:

1
2
3
4
5
6
7
8
9
10
11
>>> s = {'a', 'b', 'c'}
>>> s.add('d')
>>> s
{'a', 'd', 'c', 'b'}
>>> s.update('e')
>>> s
{'a', 'b', 'e', 'd', 'c'}
# 添加已经存在的元素 a
>>> s.add('a')
>>> s
{'a', 'b', 'e', 'd', 'c'}

删除元素使用 remove 方法,如下所示:

1
2
3
4
>>> s = {'a', 'b', 'c'}
>>> s.remove('c')
>>> s
{'a', 'b'}

清空集合使用 clear 方法,如下所示:

1
2
3
4
>>> s = {'a', 'b', 'c'}
>>> s.clear()
>>> s
set()

4.5.3 其他函数

获取集合的长度,同样使用 len 方法,如下所示:

1
2
3
>>> s = {'a', 'b', 'c'}
>>> len(s)
3

5 函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

5.1 自定义函数

5.1.1 函数定义

你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
  • 注意缩进格式
1
2
3
4
def functionname( parameters ):
"函数_文档字符串"
function_suite
return [expression]

如:以下为一个简单的Python函数,它将一个字符串作为传入参数,再打印到标准显示设备上。

1
2
3
4
>>> def printme(str):
... "打印传入的字符串到标准显示设备上"
... print(str)
... return

5.1.2 函数调用

定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。

这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。

如下实例调用了printme()函数:

1
2
3
4
>>> printme("博博博博博博博哥")
... printme("超超超超超超超人")
博博博博博博博哥
超超超超超超超人

5.1.3 返回值

return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。如:

1
2
3
4
5
6
>>> def sum( arg1, arg2 ):
... total = arg1 + arg2
... print "函数内 : ", total
... return total
>>> total = sum( 10, 20 )
30

5.2 参数

以下是调用函数时可使用的正式参数类型:

    必备参数
    关键字参数
    默认参数
    不定长参数

5.1.1 必备参数

必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

如调用printme()函数,你必须传入一个参数,不然会出现语法错误:

1
2
3
4
5
6
>>> printme()
Traceback (most recent call last):
File "...", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
TypeError: printme() missing 1 required positional argument: 'str'

5.1.2 关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为Python解释器能够用参数名匹配参数值。

以下实例在函数 printme() 调用时使用参数名:

1
2
>>> printme(str = "琅琊少年诸葛恪")
琅琊少年诸葛恪

关键字参数具有顺序不重要性:

1
2
3
4
5
6
7
8
>>> def whatsup(name, value):
... print("拿来吧你!")
... print(name, end=" ")
... print(value)

>>> whatsup(value="♠8", name="八卦阵")
拿来吧你!
八卦阵 ♠8

5.1.3 默认参数

调用函数时,默认参数的值如果没有传入,则被认为是默认值。如:

1
2
3
4
5
6
7
8
>>> def whatsup(name="八卦阵", value="♠8"):
... print("拿来吧你!")
... print(name, end=" ")
... print(value)

>>> whatsup(value="♣8")
拿来吧你!
八卦阵 ♣8

5.1.4 不定长参数

你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下:

1
2
3
4
def functionname([formal_args,] *var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]

加了星号(*)的变量名会存放所有未命名的变量参数。如:

1
2
3
4
5
6
7
8
9
>>> def printlist(name,*vars):
... print("name:%s\nvar:"%name,end=' ')
... for var in vars:
... print(var, end=' ')
... return

printlist('闪电','♠2','♠3','♠4','♠5','♠6','♠7','♠8','♠9')
name:闪电
var: ♠23456789

5.3 参数类型

在 python 中,类型属于对象,变量是没有类型的:

1
2
>>> a=[1,2,3]
>>> a="哈哈哈"

以上代码中,[1,2,3]是List类型,"哈哈哈"是String类型,而变量a没有类型,它仅仅是一个对象的引用(一个指针),可以是List类型对象,也可以指向String类型对象。

5.3.1 可更改/不可更改对象

在 python 中,strings,tuples和numbers是不可更改的对象,而list,dict等则是可以修改的对象。

**不可变类型:**变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。

**可变类型:**变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

5.3.2 参数传递

**不可变类型:**类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。如:

1
2
3
4
5
6
7
>>> def ChangeInt(a):
... a = 10
...
>>> b =2
>>> ChangeInt(b)
>>> b
2

实例中有int对象2,指向它的变量是b,在传递给ChangeInt()函数时,按传值的方式复制了变量b,a和b都指向了同一个Int对象,在a=10时,则新生成一个int值对象10,并让a指向它。

就是说这段代码你白写了。

**可变类型:**类似 c++ 的引用传递,如 列表,字典。如fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响

1
2
3
4
5
6
7
8
9
>>> def ChangeList(lis):
... lis.append("芜湖起飞")
... print("函数内取值: ", lis)
... return
>>> li = [1,2,3,4]
>>> ChangeList(li)
函数内取值: [1, 2, 3, 4, '芜湖起飞']
>>> print("函数外取值: ", mylist)
函数外取值: [1, 2, 3, 4, '芜湖起飞']

python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

5.4 匿名函数

5.4.1 lambda

  lambda只是一个表达式,函数体比def简单很多。
  lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
  虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
  用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。
  有些函数在代码中只用一次,而且函数体比较简单,使用匿名函数可以减少代码量,看起来比较“优雅”。

5.4.2 语法

lambda函数的语法只包含一个语句,如下:

1
lambda [arg1 [,arg2,.....argn]]:expression

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
>>> # 普通函数
... def calc(x, y):
... return x ** y
>>> calc(2,5)
32

>>> # 换成匿名函数
>>> calc = lambda x, y: x ** y
>>> print(calc(2, 5))
32

>>> # 普通函数
>>> def calc(x,y):
... if x > y:
... return x * y
... else:
... return x / y
>>> calc(2,5)
0.4

>>> # 换成匿名函数
>>> calc = lambda x,y:x * y if x > y else x / y
>>> print(calc(2,5))
0.4

然而更常见的用法是将匿名函数与其他函数配合使用。

5.4.3 和map函数

map()函数接收两个参数,一个是作用函数,一个是Iterable,map()将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回遍历序列,对序列中每个元素进行函数操作,最终获取新的序列。

例:求列表[1,2,3,4,5,6,7,8,9]返回一个n*n的列表。

1
2
3
4
5
6
7
8
9
10
11
>>> #一般解决方案
>>> li = [1,2,3,4,5,6,7,8,9]
>>> for ind,val in enumerate(li):
... li[ind] = val * val
... print(li)
[1, 4, 9, 16, 25, 36, 49, 64, 81]

#lambda解决方案
>>> li = [1,2,3,4,5,6,7,8,9]
>>> print(list(map(lambda x:x*x,li)))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

5.4.4 和reduce函数

reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

reduce(func,[1,2,3]) 等同于 func(func(1,2),3)。

例:计算序列[1,2,3,4,5,6,7,8,9]的积。

1
2
3
4
>>> from functools import reduce
>>> li = [1,2,3,4,5,6,7,8,9]
>>> print(reduce(lambda x,y:x * y,li))
362880

5.4.5 和filter函数

filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

对于序列中的元素进行筛选,最终获取符合条件的序列。

1
2
3
4
5
6
7
8
9
>>> # 在一个list中,删掉偶数,只保留奇数
>>> li = [1, 2, 4, 5, 6, 9, 10, 15]
>>>print(list(filter(lambda x:x % 2==1,li)))
[1, 5, 9, 15]

>>> # 筛选出1——200内的回数(左右对称)
>>> li = list(range(1, 200))
>>> print(list(filter(lambda x:int(str(x))==int(str(x)[::-1]),li)))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]

5.4.6 和sorted函数

sorted(iterable, key, reverse)函数接收一个key函数来实现对可迭代对象进行自定义的排序

iterable:主要有列表,字符串,元祖,集合和字典

key:接受一个函数,根据此函数返回的结果,进行排序

reverse:排序方向,默认为从小到大,reverse=True为从大到小

与sort()函数不同的是,sort()函数的返回值是在原序列基础上的排列,而sorted()返回一个新的序列。

1
2
3
4
5
6
7
8
>>> # 假设我们用一组tuple表示学生名字和成绩:
... L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
>>> # 请用sorted()对上述列表分别按名字排序
... print(sorted(L, key = lambda x : x[0]))
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
>>> # 再按成绩从高到低排序
... print(sorted(L, key = lambda x : x[1], reverse=True))
[('Adam', 92), ('Lisa', 88), ('Bob', 75), ('Bart', 66)]

6 模块与包

6.1 模块

6.1.1 简介

模块化是将程序分解为一个个的模块module,通过组合模块来搭建出一个完整的程序,便于团队开发,方便维护和代码复用。

在python中一个脚本(.py)文件就是一个模块,创建模块实际上就是创建一个.py文件,可以被其他模块导入并使用。注:

  自定义模块的时候要注意命名的规范,使用小写,不要使用大写,不要使用中文,不要使用特殊字符等。
  不要与内置模块冲突如sys等。
  在同一个包中的模块名不允许重复,在不同包中的允许重复。

  • 先创建一个package(包),再建一个文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
`# 在模块中定义变量
a = 10
b = 20

# 在模块中定义函数
def adding(x, y):
return x + y

def subbing(x,y):
return x-y

# 在模块中定义类
class calculator: # 定义一个加法计算器
@classmethod # 导入计算器模块
def sum(cls,*nums):
res = 0
for i in nums:
res += i
return res
'''
__name__ 属性是模块的内置属性,每个模块中都有该属性,当该
.py文件是主执行文件,直接被执行时,其值为 __main__ ,当该
.py文件是被调用,导入执行文件时,其值为模块名
'''
# print(__name__)# 如果这么直接这么测试,被导入文件执行时,导入文件也会打印该内容

#程序入口,类似于java中的main()方法,只在当直接调用该文件时才会执行,用来执行测试
if __name__ == '__main__' :
print(calculator.sum(1,2,3)) # 只有在当前界面执行才会打印该内容,其他文件中不会执行。`

6.1.2 使用模块

确保和定义模块处于同一个package,然后建立新的文件。
导入模块的2种方式:

方式一:import 包名.模块名 [as 别名] (别名可要可不要)
方式二: from 包名 import 模块名
from 包名.模块名 import 变量|函数|类
注:导入模块的代码可以放在任意位置,但一般都放在程序的开头。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 方式一,不定义别名
import 模块.定义模块 #导入模块

print('*' * 50)
# 方式一 定义别名
import 模块.定义模块 as m # 别名为m

# 方式二 普通方式
from 模块 import 定义模块 # 导入模块

#方式二 导入模块并传参
from 模块.定义模块 import a,b,max,min,calculato
# 导入模块,多个变量\函数\类之间用逗号隔开

6.2 包

6.2.1 基础

为了方便归类整理和避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。

举个例子,一个zhaoyun.py的文件就是一个名字叫zhaoyun的模块,一个machao.py的文件就是一个名字叫machao的模块。

现在,假设我们的zhaoyun和machao这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块,避免冲突。方法是选择一个顶层包名,比如shu,按照如下目录存放:

1
2
3
4
mycompany
├─ __init__.py
├─ machao.py
└─ zhaoyun.py

引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。现在,zhaoyun.py模块的名字就变成了shu.zhaoyun,类似的,machao.py的模块名变成了shu.machao。

每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。init.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是shu。

类似的,可以有多级目录,组成多级层次的包结构。比如如下的目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
sanguosha
├─ shu
│ ├─ __init__.py
│ ├─ zhaoyun.py
│ └─ machao.py
├─ qun
│ ├─ __init__.py
│ ├─ zhaoyun.py
│ └─ machao.py
├─ __init__.py
├─ wei.py
└─ wu.py

6.2.2 标准库

Python提供了一个强大的标准库,内置了许多非常有用的模块,可以直接使用,不用单独安装。

完整的库及介绍可以见官网:`https://docs.python.org/zh-cn/3/library/index.html

如果嫌官方太麻烦,可以看:https://www.cnblogs.com/jiangchunsheng/p/9275881.html,https://www.cnblogs.com/aipiaoborensheng/p/7813087.htmlhttps://blog.51cto.com/12402007/2164567`

这里说明一下标准库或第三方库的使用方法:

格式: import库名(文件顶端导入库)
引用:库名.功能 即可
如:

  • sys:获取python解析的信息
  • os:对操作系统进行访问,主要是对目录或文件操作
  • math:数学运算
  • random:生成随机数
  • datetime:处理日期和时间,提供了多个类(dimedelta是处理时间类)
  • time:处理时间,关于时间加减 可以参考:https://blog.csdn.net/xieganyu3460/article/details/82229039
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import sys
import os
import math
import random
#时间库的两种导入方法。用法不一样
#import datetime
#print(datetime.datetime.now()) #import方法导入使用方法
from datetime import datetime,timedelta #为了简便,建议使用这种方式导入时间库
#print(datetime.now()) #from导入使用方法
import time

print(sys.version) #python版本
print(sys.platform) # 系统平台
print(sys.argv) #命令行参数
print(sys.path) #模块搜索路径,包含了python解析器查找模块的搜索路径
print(sys.modules) #显示当前程序中引入的所有模块
print(sys.getdefaultencoding()) #默认字符集
#sys.exit('程序退出(自定义提示内容)') #退出解析器
print('——————————————————————————————————————————————')

print(os.name) #操作系统的类型
print(os.environ) #系统的环境变量
print(os.getcwd()) #当前的目录
print(os.listdir('d:/')) #列出指定目录的内容
print(os.path.exists('d:/newfile')) #判断路径是否存在
#os.system('ping baidu.com') #执行系统命令
print('——————————————————————————————————————————————')

print(math.pi) #获取圆周率
print(math.ceil(3.4)) #向上取整(结果4)
print(math.floor(3.4)) #向下取整(结果3)
print(math.pow(2,3)) #开平方,如这就是2的3次方
print(math.trunc(2.777)) #去尾取整 (结果为2)
print(round(2.777)) #结尾取整(结果为3)
print(round(3.1415925,3)) #四舍五入,保留3位小数
print('——————————————————————————————————————————————')

print(random.random()) # 默认返回[0,1]之间的随机浮点数
print(random.randint(1,101)) #返回1-101 之间的随机整数
print(random.sample([1,2,3,33,44,16,66,7],2)) #在数组中随机返回2个数值

#print(datetime.datetime.now()) #import方法导入使用方法
print(datetime.now()) #默认显示当前时间 年月日,时分秒毫秒
print(datetime.strftime(datetime.now(),'%Y-%m-%d %H:%M:%S')) #将datetime转换为指定格式的str,不支持中文。
#如果要支持中文,可以使用占位符的方式实现。
print(datetime.strftime(datetime.now(),'%Y{0}-%m{1}-%d{2} %H:%M:%S').format('年','月','日'))
print(datetime.strptime('2020-04-11','%Y-%m-%d')) # 将str转换为datetime格式
#时间加减,需要另外一个库,格式是这样的: from datetime import datetime,timedelta
print('明天:',datetime.now()+timedelta(days=1)) #timedelta表示两个时间之间的时间差,可以用来进行日间的加减操作
#timedelta(weeks=0, days=0, hours=0, minutes=0, seconds=0, milliseconds=0, microseconds=0, )
# 依次为 "周" "天", "时","分","秒","毫秒","微秒"
print('——————————————————————————————————————————————')

print(time.time()) #返回当前的时间戳
print(int(time.time())) #秒级时间戳
print(int(time.time() * 1000)) #毫秒级时间戳
time.sleep(5) #休眠5秒`

6.2.3 第三方包

PYthon社区提供了大量的第三方包,使用方式与标准库类似。
安装第三方包:

1、使用包管理工具:pip(随python一起安装的)
语法:pip install 模块名
使用方法参考:https://jingyan.baidu.com/article/466506583fec5af549e5f825.html
2、使用pycharm 来安装:
方法:file-settings(设置)-Project:python-Project Interpreter
注意要选择当前版本:
在这里插入图片描述

安装新模块:
在这里插入图片描述

搜索模块名并安装:
在这里插入图片描述

成功安装界面:
在这里插入图片描述

pycharm安装报错处理方法:
报错信息:
在这里插入图片描述

问题说明:是因为pychram 安装脚本有问题。
处理方法:退出pycharm,右键pycharm-属性-打开安装位置 在这里插入图片描述

打开以后默认在bin目录,返回上一级-打开plugins-python-helpers目录-编辑packaging_tool.py文件
如果找不到这个目录:在安装目录首页搜索:packaging
在这里插入图片描述

定位到packaging_tool.py文件后
在这里插入图片描述

右键打开方式-写字板打开-找到 do_install
在这里插入图片描述

我的上面是正常的,把你的这2个内容全部删了,替换为

1
2
3
4
5
`def do_install(pkgs):
run_pip(['install'] + pkgs)

def do_uninstall(pkgs):
run_pip(['uninstall', '-y'] + pkgs)`

替换完以后重写打开pycharm并重新安装模块即可。

如果替换为上面的不行则用下面的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
`def do_install(pkgs):
try:
# import pip
try:
from pip._internal import if __name__ == '__main__':
except Exception:
from pip import if __name__ == '__main__':
except ImportError:
error_no_pip()
return main(['install']+pkgs)

def do_uninstall(pkgs):
try:
#import pip
try:
from pip._internal import main
except Exception:
from pip import main
except ImportError:
error_no_pip()
return main(['uninstall','-y'] + pkgs)`

注意格式:如果放进去格式乱了,用其他文件打开,notepad或者pycharm打开把
在这里插入图片描述

默认是在python官网下载的模块(如果模块较大,可能会比较慢),可以更改下载源
在这里插入图片描述

比如https://pypi.python.org/simple改成https://pypi.douban.com/simple

6.2.4 pyecharts的使用

百度搜索:echarts,点击实例,你可以发现一个很骚气的东西
在这里插入图片描述

随便点开一个,发现,卧槽,还有代码,如果把这作为背景,这也太帅了把,当然,我臆想的而已,我现在还不知道这能不能作为网页之类的背景呢!!!!
在这里插入图片描述

pyecharts是一个用于Echarts图表的类库,便于在Python中根据数据生成可视化的图标,Echarts是百度开源的一个数据可视化JS库,主要用来进行数据可视化。

各种图标使用方式见官方(太炫酷了把):http://pyecharts.org/#/zh-cn/basic_charts?id=funnel%ef%bc%9a%e6%bc%8f%e6%96%97%e5%9b%be

使用前得先安装pyecharts模块:
在这里插入图片描述

使用前需要注意一个坑!!! 包名和文件名 不能有中文,否则 就会报错!!!
包和类全部无中文!!!
运行无报错以后,在同包下面会生成一个 html结尾的文件。

1
2
3
4
5
6
7
8
9
`from pyecharts.charts import Bar

bar = Bar()
bar.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
bar.add_yaxis("地表最强yy商铺", [5, 20, 36, 10, 75, 90])
# render 会生成本地 HTML 文件,默认会在当前目录生成 render.html 文件
# 也可以传入路径参数,如 bar.render("mycharts.html")
bar.render("mycharts.html")
bar.render()`

在这里插入图片描述

现在运行 自动生成的.html结尾的文件!
就会打开一个网页,里面就是表格信息了!!!!
在这里插入图片描述

但是,我第二次弄的时候导包突然报错了!!!
葛优瘫坐在椅子上 深思 …
葛优瘫坐在椅子上 深思 …
突然想到,我包名是pyecharts , 模块是pyecharts。。我from导入的时候会不会系统默认给我导入我创建的这个包了啊???
我把我这个包名改了试试,报错。唉 果然不是这个问题啊!
在这里插入图片描述

难道是 文件名有错? demo01和其他包里的重复了? 我又把 文件名后面都加了个test,然后还是不行啊,我以为没生效,重启了软件,还是不行啊。哎 看来真出问题了。
在这里插入图片描述

都不行怎么办? 凉拌啊 凉了啊!!! 哎
要不重新导入模块试试,试试把 反正也就这样了!!!
咦? 可以了,我仔细看了一下,卧槽!!!! 就是我之前想的那样,导入的模块系统默认导入同名的包了!! 然后我改了包名,这名字也改了,没注意看啊!! 坑爹啊 坑爹啊!!! 细心点 细心点啊!!!
在这里插入图片描述

上诉能正常执行以后,参加:http://gallery.pyecharts.org/#/Map3D/map3d_china_base
这是官方给的 所有代码!!!

随便来几个官网中的代码测试:
demo1: 生成3D柱形图
执行方式,执行该代码就会自动生成一个html的文件,再打开自动生成的html即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
`import random

from pyecharts import options as opts
from pyecharts.charts import Bar3D

x_data = y_data = list(range(10))

def generate_data():
data = []
for j in range(10):
for k in range(10):
value = random.randint(0, 9)
data.append([j, k, value * 2 + 4])
return data


bar3d = Bar3D()
for _ in range(10):
bar3d.add(
"",
generate_data(),
shading="lambert",
xaxis3d_opts=opts.Axis3DOpts(data=x_data, type_="value"),
yaxis3d_opts=opts.Axis3DOpts(data=y_data, type_="value"),
zaxis3d_opts=opts.Axis3DOpts(type_="value"),
)
bar3d.set_global_opts(title_opts=opts.TitleOpts("Bar3D-堆叠柱状图示例"))
bar3d.set_series_opts(**{"stack": "stack"})
bar3d.render("bar3d_stack.html")`

效果图:
在这里插入图片描述

demo2:三维地图

1
2
3
4
5
6
7
8
9
10
11
12
13
`from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker

c = (
Map()
.add("中国", [list(z) for z in zip(Faker.provinces, Faker.values())], "china")
.set_global_opts(
title_opts=opts.TitleOpts(title="测试而已,数据没有意义(ccx著)"),
visualmap_opts=opts.VisualMapOpts(max_=500, is_piecewise=True),
)
.render("map_visualmap_piecewise.html")
)`

运行结果:
在这里插入图片描述