Python 基础知识笔记

173 阅读52分钟

1 下载安装 Anaconda

  • 去官网下载安装包,双击安装包安装,安装路径可自定义安装。
  • 安装完成后设置环境变量,在环境变量中的 path 中添加 Anaconda 的安装路径及路径下的 Scripts 的路径
  • 然后打开 cmd 命令窗口,输入 conda --version 校验是否安装成功
  • 启动 Anaconda ,在电脑搜索的地方搜索 “Jupyter Notebook” 进行启动。

2 基础知识

2.1 print:用于字符串打印

语法:

print(value,...,sep='',end='')
# 1. value:输入一个或多个要打印的字符串
# 2. sep:代表可自定义 value 之间的符号,默认为空格
# 3. end:代表可自定义 value 结尾的符号,默认为换行符号
print('lemon','apple','banana',sep=',',end='.')

2.2 注释与换行操作

单行注释:

print('hello','world') # 向屏幕输出 hello world

多行注释:

'''
先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。
然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。
诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
'''

"""
宫中府中,俱为一体,陟罚臧否,不宜异同。
若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
"""

print('侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。')
print('愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。')
print('将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰能,是以众议举宠为督。')

换行:

print('愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。\
亲贤臣,远小人,此先汉所以兴隆也;\
亲小人,远贤臣,此后汉所以倾颓也。\
先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。\
侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。')

2.3 单引号、双引号及转义字符

print('臣本布衣,躬耕于南阳')
print("臣本布衣,躬耕于南阳")
print(''' I'm pythonic,I said:"Practice makes perfect" ''')
print(""" I'm pythonic,I said:"Practice makes perfect" """)

# 用反斜杠(\)转义特殊字符
print('\n')
print('\\n')
# 可以用 r 和 R 来定义原始字符串
print(r'\\n')  # 打印的是 \\n
print(R'\\n')  # 打印的是 \\n

2.4 运算符和数学函数

运算符:

# 乘方
4 ** 4  # 表示4的4次方,结果:256

# 取整
20 // 6  # 结果:3

# round 四舍五入
round(8.9)  # 四舍五入保留到整数位
round(10.671,2)  # 四舍五入保留小数点后两位

# abs绝对值取整
abs(-1)

math 数学函数:

import math
math.ceil(5.01)  # 向上取整
math.floor(5.99)  # 向下取整
math.trunc(10.9)  # 截取整数位
math.pow(2,4)  # 幂运算,表示2的4次方

2.5 字符串

特点:由单引号、双引号、三个单引号、三个双引号 组成

'A' + 'B'  # 结果:AB
'A' * 3  # 结果:AAA

'python'[1]  # 结果:y
'python'[-2]  # 结果:o
'python'[1:4]  # 结果:yth
'python'[2:]  # 结果:thon
  1. String.strip([chars]) :

    • chars为空:去除头尾空白符(\n、\r、\t、'',即换行、回车、制表符、空格)
    • chars不为空:将chars拆成一个一个字符,去除头尾指定的字符
'   abc123abc   '.strip()  # 结果:'abc123abc' 
'abc123abc'.strip('ab')  # 结果:'c123abc' 
'abc123abc'.strip('ba')  # 结果:'c123abc' 
'eabc123abc'.strip('ba')  # 结果:'eabc123abc' 
'abc123cba'.strip('bac')  # 结果:'123' 
'abc12abc3cba'.strip('bac')  # 结果:'12abc3' 
  1. String.lstrip([chars]) :
'   abc123abc   '.lstrip()  # 结果:'abc123abc   ' 
  1. String.rstrip([chars]) :
'   abc123abc   '.rstrip()  # 结果:'   abc123abc' 
  1. 判断字符串开头结尾字符:
'python'.startswith('p')  # 结果:true 
'python'.endswith('n')  # 结果:true 
  1. 返回字符串中字符的位置:
'apple'.find('p')  # 结果:1
'apple'.index('p')  # 结果:1

'apple'.find('m')  # 结果:-1
'apple'.index('m')  # 结果:报错
  1. 字符串替换:
'python'.replace('t','TT')  # 结果:'pyTThon'
'python'.replace('python','hello')  # 结果:'hello'
  1. len(S): 返回字符串长度
  2. S.count('x'): 查找某个字符在字符串里面出现的次数
  3. S.upper(): 将字符串中小写字母,转为大写字母
  4. S.lower(): 将字符串中大写字母,转为小写字母
  5. S.center(n,'-'): 把字符串放中间,两边用-补齐,n为字符串长度,若n小于字符串长度则返回原值
  6. 字符串格式化:% format
    • %s: 使用 str() 函数进行字符串转换
    • %d: 转为十进制整数
    • %f: 转为浮点数
'hello %s' %('world')  # 结果:'hello world'
'hello %s,%s' %('world')  # 结果:报错
'hello %s,%s' %('world','apple')  # 结果:'hello world,apple'
'I am %{name}s, I am %{age}s years old' %{'name':'cily','age':16}  # 结果:'I am cily, I am 16 years old'

'I am %d years old' % (16)  # 结果:'I am 16 years old'

'%f' % (3.14)  # 结果:'3.140000'
'%.3f' % (3.14)  # 结果:'3.140'

'hello {}'.format('world')  # 结果:'hello world'
'hello {} {}'.format('world','python')  # 结果:'hello world python'
'hello {1} {0}'.format('world','python')  # 结果:'hello python world'
'I am {name}, I am {age} years old'.format(name = "cily",age = 16)  # 结果:'I am cily, I am 16 years old'

2.6 Number(数字):整形、浮点型、复数

Python数字类型:整形(int)、浮点型(float)、复数(complex)、布尔型(bool)

进制转换:

  • bin 转化为二进制 0b1010
  • oct 转化为八进制 0o12
  • int 转化为十进制 10
  • hex 转化为十六进制 0xa
  1. 浮点型(float):
type(10)  # int
type(10.)  # float

print(3+1.0)  # 4.0
print(type(3+1.0))  # <class 'float'>

# Python 中相除,默认返回浮点型
print(3/1)  # 3.0
print(type(3/1))  # <class 'float'>
# 整除
print(3//1)  # 3
print(type(3//1))  # <class 'int'>
  1. 复数(complex):complex([real[,imag]])
complex(3,)  # (3+0j)
complex(3,4)  # (3+4j)
complex(3,4).real  # 实部,结果:3.0
complex(3,4).imag  # 虚部,结果:4.0
complex('3',4)  # 报错
complex('3+4j')  # (3+4j)
complex('3 + 4j')  # 报错
  1. 布尔类型:判断条件是否成立,只有 True、False
int(True)  # 1
int(False)  # 0
isinstance(1,int)  # True
isinstance(0,int)  # True
isinstance(True,int)  # True
isinstance(False,int)  # True

bool(1)  # True
bool(0)  # False
bool(-1)  # True
bool(None)  # False
bool()  # False
bool('')  # False
bool(' ')  # True
bool([])  # False
bool({})  # False

2.7 列表、元组、字典

  1. 列表
# 创建空列表
list[]
[]

# 创建只有一个元素的列表
[1,]
[1]

# 创建包含不同数据类型的列表
['a',1,2,3.14,[1,2,3,4]]

# 列表操作
['a',1,2,3.14,[1,2,3,4]][0]  # 'a'
['a',1,3.14,[1,2,3,4]][3][2]  # 3
[1,2] + [3.4]  # [1,2,3.4]
[1,2] - [3.4]  # 报错,列表间不支持相减操作
[1,2] * 5  # [1,2,1,2,1,2,1,2,1,2]
[1,2] / [3.4]  # 报错,列表间不支持相除操作
  • list.count(x) : 统计列表中 x 出现的次数,若不存在则返回 0
  • list.append(x) : 向列表尾部追加成员 x
  • list.extend(l): 向列表尾部追加另外一个列表 l
  • list.index(x) : 返回参数 x 在列表中的序号,若不存在则报错
  • list.insert(index, object) : 在列表指定位置插入数据
  • list.pop() : 默认删除列表尾部成员,并返回删除的成员
  • list.remove(x) : 删除列表中指定成员(有多个则只删除第一个),若指定成员不存在则报错
  • list.reverse() : 将列表中的成员顺序颠倒
  • list.sort() : 排序(要求成员间可排序,否则报错)
x = [1,2,3,4,2,5,3,8,2,9,0,19,2,14,12,34,25]
x.count(2)  # 4
[1,2,3].append([7,8,9])  # [1,2,3,[7,8,9]]
[1,2,3].extend([7,8,9])  # [1,2,3,7,8,9]
[11,12,13,14].pop()  # 14
[11,12,13,14].pop(1)  # 12
  1. 元组(tuple):

元组基本形式:圆括号 () 包围的数据集合,可以通过序号访问元素。一种特殊形式的列表。一但创建不可变。

【注意】:元组的元素不可变,但当元组元素为列表或字典数据类型时,列表或字典内的内容是可以变的。

# 创建空元组
()
tuple()
(1,)  # 创建只有一个元素的元组不能省略这个逗号
type((1,))  # tuple
type((1))  # int
a = (1,2,3,[4,5,6])
a[1] = 10  # 报错
a[3][0] = 10  # a的值变为 (1,2,3,[10,5,6])
  • 元组常见函数:
    • len(tuple) # 返回元组数量
    • max(tuple) # 返回元组最大值
    • min(tuple) # 返回元组最小值
    • tuple(seq) # 将序列转为元组
  1. 字典基本操作:
{}  # 创建空字段
dict()  # 创建空字段

fruits = {"lemon":5,"apple":10}
fruits['lemon']  # 5
fruits['pear']  # 通过不存在的键访问成员会报错

fruits['lemon'] = 20
fruits['pear'] = 15

del fruits['pear']  # 删除pear
fruits.clear()  # 清空整个字典

del fruits  # 删除 fruits

字典的键的数据类型可以是:字符串、数字、元组不可变数据类型,不能为列表类型。

  • dict.copy() # 复制字典
  • dict.get(key,default=None) # 获取key对应的值,若key不存在则返回default
  • dict.items() # 获取由键和值组成的迭代器
  • dict.keys() # 获取键的迭代器
  • dict.values() # 获取值的迭代器
  • dict.pop(key,[default]) # 删除key:value的指定成员对。若key不存在,则返回default
  • dict.popitem() # 从字典末尾删除key:value,并返回key:value
  • dict.update({key:value}) # 从另外一个字典更新成员(存在则覆盖,若不存在就创建。)
  • dict.setdefault(key,default=None) # 若字典存在key,则返回对应的值(不会覆盖原值)。若不存在,则建立一个key:default的字典成员。
fruits1 = {'lemon':5,'apple':10}
fruits2 = fruits1.copy()
fruits1.get('pear','该键不存在')
fruits1.items()  # dict_items([{'lemon':5},{'apple':10}])
fruits1.keys()  # dict_keys(['lemon', 'apple'])

2.8 Set集合类型

集合(set):无序、不重复的数据集合。无法通过键访问成员。可以使用大括号{}或者set()函数创建集合。

# 注意:创建一个空集合必须用 set() 而不是 {},因为 {} 是创建一个空字典。
type(set())  # set

a = {1,2,3,4}
type(a)  # set

b = {1,1,3,3,2,2,4,4}  # 最终 b 的值为 {1,3,2,4}

c = ['lemon','lemon','apple','apple']
set(c)  # 去重,结果:{'lemon','apple'}

d = {1,2,3,4,5,6}
len(d)  # 6
1 in d  # True
7 in d  # False

d - a  # 得出集合间的差集 {5,6}
d & a  # 得出集合间的交集 {1,2,3,4}
d | a  # 得出集合间的并集 {1,2,3,4,5,6}

2.9 Python 基本数据类型总结

  1. 数字(Number):整型(int)、浮点型(float)、复数(complex)、布尔型(bool)
  2. 序列:列表(可变序列)、字符串(不可变序列)、元组(不可变序列)
  3. 字典:无序,没有索引,通过键值对访问,键是不可变的
  4. 集合:无序,没有索引,没有重复元素

2.10 变量

命名规则:只能包含字母、数字、下划线,不能以数字开头。最好用小写字母。

关键字:

False、class、finally、is、return、True、continue、for、lambda、try、None、def、from、nonlocal、while、and、del、global、not、with、as、elif、if、or、yield、assert、else、import、pass、break、raise、except、in

2.11 运算符

  1. 算术运算符: + - * / % // **
  a = {1,2,3,4}
  b = {1,2}
  a - b  # 得出集合间的差集 {3,4}

  'python ' * 3  # 字符串 'python python python '
  [1,2,3] * 3  # 列表 [1,2,3,1,2,3,1,2,3]
  (1,2,3) * 3  # 元组 (1,2,3,1,2,3,1,2,3)

  10 // 3  # 取整运算 3
  10.0 // 3  # 取整运算 3.0
  1. 赋值运算符:= += -= *= /= %= //+ **=

  2. 比较(关系)运算符:== != <> < > => <=

1 == 1  # True
1 == 1.0  # True
# 不等于 <> 适用于 Python2
# 不等于 != 适用于 Python2、3
'a' < 'b'  # True 字符串比较大小通过ASCII码比较,ord('a')为97,ord('b')为98,注意ord()函数参数只能传入一个字符
[1,2,3] == [1,3,2]  # False
[1,2,3] < [1,3,2]  # True
{1,2,3} == {1,3,2}  # True
{1,2,3} < {1,3,2}  # False
{'lemon':5,'apple':4} == {'lemon':5}  # False
{'lemon':5,'apple':4} < {'lemon':5}  # 报错,字典不支持比较大小

  1. 逻辑运算符: and or not
# 布尔类型为 0 None 控制(空字符串、空列表、空元组、空字典、空集合)的时候,返回False
bool('')  # False
bool(' ')  # True
0 and 2  # 0
1 and 2  # 2
2 and 1  # 1
0 or []  # []
[] or 0  # 0
0 or 2  # 2
1 or 2  # 1
not 1  # False
not 0  # True

  1. 成员运算符:判断一个元素是否在另外一组元素中,返回布尔类型。 in not in
a = 'lemon'
a in 'hello lemon'  # True
a not in 'hello lemon'  # False
b = 1
b in [1,2,3,4]  # True
b in {1,2,3,4}  # True
b in (1,2,3,4)  # True
# 字典的成员运算,针对的是字典key:value中的key
c = 5
d = {'lemon':5}
c in d  # False
e = 'lemon'
e in d  # True

  1. 身份运算符:比较两个对象,内存地址是否相等,返回布尔类型。 is is not
a = 1
b = 1
a is b  # True 可通过id(a) 和 id(b) 来查看内存地址
c = 1.0
a == c  # True
a is c  # False

d = {1,2,3}
e = {2,1,3}
d == e  # True
d is e  # False

f = {'lemon':5,'apple':3,'pear':4}
g = {'apple':3,'pear':4,'lemon':5}
f == g  # True
f is g  # False
  1. 位运算符:把数字转为二进制运算。 & | ^ ~ << >>
bin(4)  # 0b100
bin(5)  # 0b101
# & 按位与:两个相应位都为1,则该位为1,否则为0
4 & 5  # 4
int('100',2)  # 4
# | 按位或:两个相应位至少有一个为1,则该位为1,否则为0
4 | 5  # 5
int('101',2)  # 5
# ^ 按位异或:两个相应位相异的时候,则该位为1,否则为0
4 ^ 5  # 5
int('001',2)  # 1

2.12 值类型与引用类型

  • 值类型是不可变的:数字、str、tuple
  • 引用类型是可改变的:list、dict、set

2.13 if 语句

语法:

if condition:
  true_expression
else:
  false_expressions
other_expression


if condition1:
  expression1
elif condition2:
  expression2
elif condition3:
  expression3
else:
  expressions
a = True
if a:
  print('条件成立')
print('if执行完成')
'''
打印结果如下:
    条件成立
    if执行完成
'''

a = False
if a:
  print('条件成立')
print('if执行完成')
'''
打印结果如下:
    if执行完成
'''

input() 函数会接收输入数据,返回为 string 类型

num = input('请输入数字:')
# 输入数字5后
num  # 5
type(num)  # str
num = int(num)
type(num)  # int

2.14 for循环 / while 循环

  1. for循环:循环/遍历一个可迭代对象,主要是用来遍历 序列(列表、字符串、元组)、字典和集合

语法:

for 循环变量 in 可迭代对象:
  <语句1>
else:
  <语句2>

# else 也可以与 for 循环进行搭配,当 for 循环遍历完成后,执行 else 里面的内容。

遍历字符串:

words = 'I am lemon'
for word in words:
  print(word)
  print(word,end = '')

列表遍历:

fruits_list = ['banana','mango','lemon']
for i in fruits_list:
  print(i)

字典遍历:

fruits_dict = {'banana':5,'mango':1,'lemon':7}
for key in fruits_dict.keys():
  print(key)


for val in fruits_dict.values():
  print(val)


for key,val in fruits_dict.items():
  print(key,val)
complex_list = [['banana','mango','lemon'],[1,2,3]]
for x in complex_list:
  for y in x:
    print(y)

函数 - range()

语法:

range(start, end[, step])
# start:计数从 start 开始,默认从 0 开始,例如: range(10) 等价于 range(0, 10)
# end:计数到 end 结束,但不包含 end,例如:range(0, 10) 是 [0,1,2,3,4,5,6,7,8,9] 没有 10
# step:步长,默认为1。例如:range(0,10) 等价于 range(0,10,1)
# range 里面只能是整型类型

for 循环变量名 in range(start,end[,step]):
  <执行语句1>
else:
  <执行语句2>
for i in range(0,10,2):
  print(i, end='')  # 打印的是 0 2 4 6 8

continue:结束本次循环,进入下一次循环遍历

break:结束当前循环

fruits = ['apple','lemon','pear','lemon','banana','grape','banana','apple']
for i in fruits:
  if i == 'lemon':
    continue
  if i == 'grape':
    break
  print(i, end='')

4 种常用迭代函数

1、enumerate(seq)  # 编号迭代
2、sorted(seq)  # 排序迭代
3、reversed(seq)  # 翻转迭代
4、zip(seq1,seq2,seq3....)  # 并行迭代
seq 为可遍历/可迭代的对象,如列表、字符串、元组
# enumerate 编号迭代:在迭代的时候既返回序列中的编号(默认从0开始),又返回序列中的元素
# 需要两个循环变量,分别接收编号和元素的值
a = 'abcde'
for index,value in enumerate(a)
  print(index,value)

# sorted:for 循环变量的时候,默认先遍历序列中较小的值,后遍历序列中较大的值
# 可迭代对象中的元素,需要是可排序的同类数据
a = [1,5,4,2]
# 从小到大打印
for i in sorted(a)
  print(i)
# 从大到小打印
for i in sorted(a,reverse = True)
  print(i)

# reversed:将可迭代对象中的元素,从尾到头进行遍历
a = [1,5,4,2]
for i in reversed(a)
  print(i)

# zip:同时遍历可迭代对象中同一序号元素
# 如果元素长度不一致,只遍历到最短的序列长度
x = [1,2]
y = [3,4]
z = [5,6,7]
for a,b,c in zip(x,y,z)
  print(a,b,c)
  1. while 循环 语法:
while <条件>:
  <语句1>
else:
  <语句2>

# while 循环体内必须得存在更改条件的语句,否则很容易进入死循环
a = 1
while a<10:
  print(a)
  a += 1
else:
  print('执行结束')

2.15 猜数字游戏

import random

random_num = random.randint(0,9)

times = 3

while times>0:
  guess_num = int(input('请输入0-9整数:'))

  if guess_num>random_num:
    print('大了')
  elif guess_num<random_num:
    print('小了')
  else:
    print('恭喜你猜中啦,正确答案是:'+str(random_num))
    break
  times -= 1

  if times == 0:
    print('你三次都没有猜中,正确答案是:'+str(random_num))

2.16 函数的使用

print('lemon','pear',seq=',',end='*')

2 ** 3  # 2的3次方
# 等价于
pow(2,3)

函数的基本形式:

def <函数名> (参数):
  <函数语句>
  return  <返回值>

# def:声明一个函数
# 函数名:不要定义为 Python 关键字,不要与 Python 内置函数同名
# 函数参数
# 默认两个空格缩进的函数语句,表示属于该函数
# return 后可以没有返回值,也可以省略return语句
# return 后没有返回值或不写return语句,默认返回 None

# 查询 Python 关键之: help('keywords')
# 查询 Python 内置函数: dir(__builtins__)

# 关于函数的参数:
# 参数类型有:必须参数 、 可变参数  、 默认值参数 、 可变关键字参数
def func_name(param1,*args,param2=0,**kwargs):
  pass
# param1:必须参数,定义了多少个参数,就必须得传递多少个参数
# *args:可变参数,可以传递任意个参数
# param2:默认值参数,给参数赋默认值
# **kwargs:可变关键字参数,可以传递任意个关键字参数
# 参数使用顺序: 必须参数 可变参数 默认值参数 关键字可变参数

参数:

def details(apple,lemon):
  print('apple的数量:'+apple)
  print('lemon的数量:'+lemon)
details(3,4)
details(lemon=8,apple=10)
# 关键字参数:增强代码可读性,不需要强制记忆参数顺序,可任意调换参数传递的顺序

def message(name,age,sex='male',nationality='China'):
  print('姓名:' + str(name))
  print('年龄:' + str(age) + '岁')
  print('性别:' + str(sex))
  print('国籍:' + str(nationality))
# 默认值参数:如果需要修改默认值参数,建议使用关键字参数,对默认值参数进行重新赋值。关键字参数可以不遵循默认值顺序
message('lemon',18)
message('Alice',22,sex='female',nationality='USA')

# 序列解包:将序列中的元素平铺出来,按照顺序分别赋值给多个变量
# 序列:字符串、列表、元组
s = '123'
a,b,c = s
print('a的值为:' + str(a) + ' 类型为:' + str(type(a)))
print('a的值为:' + str(b) + ' 类型为:' + str(type(b)))
print('a的值为:' + str(c) + ' 类型为:' + str(type(c)))
# 赋值的变量数量,需要与序列中的元素数量一致

# 可变参数:可以传递任意个参数,这些参数在函数调用时自动组装为一个 tuple
def func_args(*args):
  print(args)
  print(type(args))
func_args()  # 打印的args为:() , 打印的type(args)为:<class 'tuple'>
func_args(1,2)  # 打印的args为:(1,2) , 打印的type(args)为:<class 'tuple'>
a = (1,2)
func_args(a)  # 打印的args为:((1,2),) , 打印的type(args)为:<class 'tuple'>
func_args(*a)  # 打印的args为:(1,2) , 打印的type(args)为:<class 'tuple'>
# * 星号的作用是将元组里面的元素平铺出来,传递到可变参数的函数里面
# 如果想将一个序列内的元素平铺出来,传递到可变参数的函数里面,可使用序列解包操作
# 可变参数:可以传递任意个参数,也可传递一个序列,序列前面需要加上一个 *
def add_all(*args):
  sum = 0
  for i in args:
    sum += i
  return sum

# 可变关键字参数:可传递任意个关键字参数,这些关键字参数在函数调用的时候会自动组装为一个 dict
def func_kwargs(**kwargs):
  print(kwargs)
  print(type(kwargs))

func_kwargs()  # 打印的kwargs为:{} , 打印的type(kwargs)为:<class 'dict'>
func_kwargs(lemon=5,apple=10)  # 打印的kwargs为:{'lemon':5,'apple':10} , 打印的type(kwargs)为:<class 'dict'>
fruits = {'pear':5,'banana':6}
func_kwargs(fruits)  # 报错
func_kwargs(**fruits)  # 打印的kwargs为:{'pear':5,'banana':6} , 打印的type(kwargs)为:<class 'dict'>

2.17 作用域

Python 作用域:

  1. L (Local) 局部作用域
  2. E (Enclosing) 嵌套函数外层非全局作用域
  3. G (Global) 全局作用域
  4. B (Built-in) 内建作用域

变量:全局变量、局部变量

Python 没有块级作用域

if 5>0:
  lemon = 5
print(lemon)  # 5

for i in range(10):
  lemon = 9
print(lemon)  # 9

i = 1
while i<3:
  lemon = 3
  i += 1
print(lemon)  # 3

作用域链:具有链式查找特性

  • 特点:
    1. 函数内部引用变量,会优先引用最近局部变量
    2. 函数内部引用变量,会逐级向上寻找

global关键字:

def fruit():
  lemon = 5
fruit()
print(lemon)  # 报错

def fruit():
  global lemon,pear  # 使用 global 关键字,可声明改变量为全局变量
  lemon = 5
  pear = 10
fruit()
print(lemon,pear)  # 5 10

banana = 5
def fruit():
  banana = 10
  print('函数内部的banana为:' + str(banana))
fruit()
print('全局的banana为:' + str(banana))
# 打印结果为:
# 函数内部的banana为:10
# 全局的banana为:5

# 使用 global 关键字给全局变量重新赋值
banana = 5
def fruit():
  global banana
  banana = 10
  print('函数内部的banana为:' + str(banana))
fruit()
print('全局的banana为:' + str(banana))
# 打印结果为:
# 函数内部的banana为:10
# 全局的banana为:10

程序运行第一个 return 语句后,大多数情况下会跳出该函数,不再执行之后代码

# try excepy finally

# return 返回多个结果
def fruit(lemon,apple):
  lemon = lemon * 2
  apple = apple * 2
  return lemon,apple

2.18 斐波那契数列

斐波那契数列(Fibonacci sequence),又称黄金分割数列:
1,1,2,3,5,8,13,21,34,……
这个数列从第三项开始,每一项都等于前两项之和
在数学上的递推方法:
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2)  (n>=3,n∈N*)
# 实现:用户输入任意数字,返回第N项数字
def fib(num):
  if num <= 0:
    raise Exception('数字要大于0')  # 中断函数
  if num == 1 or num == 2:
    return 1
  return fib(num-1) + fib(num-2)

将第一项到第N项结果存为一个列表:

# 列表推导式
# [循环变量名 for 循环变量名 in 可迭代对象 if 条件判断]

a = []
for i in range(10):
  a.append(i)
a  # [0,1,2,3,4,5,6,7,8,9]

b = [i for i in range(10)]
b  # [0,1,2,3,4,5,6,7,8,9]

b = [i for i in range(10) if i>5]
b  # [6,7,8,9]

num = int(input('请输入数字:'))
fibs_list = [fib(i) for i in range(1,num+1)]
fibs_list  # 

2.19 面向对象

  1. 面向过程:核心是在过程二字,面向过程设计思维,就好比精心设计好一条流水线,考虑周全,相应时候处理相应问题。
  • 优点:将复杂的问题流程化,进而简单化
  • 缺陷:扩展性差(如果更改需求,可能整个代码都需要重写,牵一发而动全身)

面向过程适用一些简单的、固定的、不需要更新迭代的问题,如果任务复杂,且需要不断更新迭代和维护的,推荐使用面向对象。

面向过程:

def test(x,y):
  if x > y:
    return x
  elif x < y:
    return y
  return x + y
  1. 面向对象:对真实世界的模拟

面向对象编程特点:

  1. 可以编写表示真实世界中的事物和情景的类,并基于这些类来创建对象
  2. 可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率

面向对象三大特点:

  1. 封装性: 将对象的特征与行为保存起来
  2. 继承性: 通过继承,子类可快速获取父类特征与行为
  3. 多态性: 不同的子类对象,调用相同的父类方法,产生不同的执行结果

2.20 类

类:描述具有相同的特征和行为的对象的集合

  • 通过变量可以刻画类的特征
  • 通过方法可以描述类的行为

注意:类可以去定义,但不负责去执行相关方法

语法:

class 类名():

  变量  # 刻画类的特征

  # 实例方法
  def 相关方法名(self,相关参数):  # 描述类的行为
    pass

  # 类方法
  @classmethod
  def 方法名(cls,相关参数)
    print('')

  # 静态方法
  @staticmethod
  def 方法名(相关参数)
    print('')

# 关于 self
# self 名称是约定成俗的
# self 指向的是类实例化后的对象本身
# self 只有在类的方法中才会有,函数是不必带有 self 的
# self 在定义类的方法(实例方法)时是必须有的
# self 在调用时不必传入相应的参数

# 通过 @classmethod 声明一个类方法

# 静态方法:与普通函数基本上没有什么区别
# 静态方法与类、对象没有太大关系的时候,可以使用该方法
# 通过 @staticmethod 声明一个静态方法

# 成员可见性:
# public 公开性 (外部可以访问相关变量,或 外部可以调用相关方法)
# private 私有性 (外部不可以访问相关变量,或 外部不可以调用相关方法)
class Men():
  gender = 'male'
  avg_height = 1.7

  def __init__(self,name,age):
    # 初始化对象特征
    print('这是构造函数 __init__')
    self.name = name
    self.age = age
    self.__testAge = age  # 私有变量:在变量前面添加两个下划线
    self.salary = 0

  def think(self):
    print('thinking')

  def __testThink(self):  # 私有方法:在方法前面添加两个下划线
    print('thinking')

  def sleep(self):
    print('sleeping')

  def modify_salary(self,salary):
    self.salary = salary

  @classmethod
  def modify_height(cls,height):
    cls.avg_height += height  # 修改类变量
    print('Success.Now the avg_height is ' + str(cls.avg_height))
  # classmethod 类方法
  # cls 是区别于示例方法的 self

  @staticmethod
  def plus_num(x,y):
    return x + y

men = Men('lemon',18)  # 类实例化,生成一个对象
men.sleep()
men.think()
men.name  # lemon
men.__dict__  # {'name':'lemon','age':18}
men.avg_height = 1.75  # 这样修改的不是 Men 类中的 avg_height,而是相当于在类中 __init__ 创建了一个 self.avg_height = 1.75
Men.modify_height(0.05)
Men.__dict__
men.plus_num(2,3)  # 6
men.__testAge  # 报错
men.testAge  # 报错
men._Men__testAge  # 私有变量可以通过这种方式获取
men.__testThink  # 报错
men.testThink  # 报错
men._Men__testThink  # 私有方法可以通过这种方式调用
men.salary = 10  # 不建议这样直接修改实例变量的值,建议通过定义方法来修改实例变量的值
men.modify_salary(20)

构造函数:可以让模板生成不同特征的对象

继承:子类可以直接使用父类的功能,减少重复代码

super关键字:不仅可以调用父类的构造函数,也可调用父类实例方法

class Men():  # 父类 或 几类

  gender = 'male'
  avg_height = 1.7

  def __init__(self,name,age):

    self.name = name
    self.age = age

  def sleep(self):
    print('sleeping')

  def think(self):
    print('thinking')


class ChineseMen(Men):  # 子类
  def __init__(self,name,age,height):
    # self.name = name
    # self.age = age
    # 上面两行可以改为下面这一行
    # Men.__init__(self,name,age)
    # 上面一行可以改为下面这一行
    super(ChineseMen,self).__init__(name,age)
    self.height = height

  def sleep(self):
    # Men.sleep(self)
    # 上面一行可以改为下面这一行
    super(ChineseMen,self).sleep()
    print(self.name + 'is sleeping')


xiaoming = ChineseMen('xiaoming', 18, 180)
xiaoming.__dict__  # {'name':'xiaoming','age':18,'height':180}

2.21 正则表达式

import re

re.findall(pattern, string, flags)  # 搜索整个字符串,返回所有匹配项
re.match(pattern, string, flags)  # 从字符串首字符开始匹配,若首字符不匹配,则返回None,若匹配则返回第一个匹配对象
re.search(pattern, string, flags)  # 搜索整个字符串,若全都不匹配,则返回None,若匹配则返回第一个匹配对象
# pattern 正则表达式匹配规则
# string 要进行匹配的字符串
# flags 可选参数,进行特定条件的匹配
re.sub(pattern, repl, string, count=0, flags=0)  # 正则替换
# pattern 正则表达式
# repl 要替换的内容,也可以传入函数
# string 被替换的字符串
# count 默认为0,代表全部替换,1代表替换1次,2代表替换2次

match_str = 'lemon&apple&lemoon&banana&lemooon&pear&lemoooon'
re.findall('lemon',match_str)  # ['lemon']
re.findall('lemo{1,4}n',match_str)  # ['lemon','lemoon','lem0ooon','lemoooon']

match_str = 'bac | bbc | bcc | bdc | bec'
re.findall('b[ab]c',match_str)  # ['bac','bbc']
re.findall('b[^ab]c',match_str)  # ['bcc','bdc','bec']
re.findall('b[abcd]c',match_str)  # ['bac','bbc','bcc','bdc']
re.findall('b[a-d]c',match_str)  # ['bac','bbc','bcc','bdc']
re.findall('b[^a-d]c',match_str)  # ['bec']

# \d 匹配一个数字字符
# \D 匹配一个非数字字符
match_str = '&a0b12c344d55&AC_'
re.findall('\d',match_str)
re.findall('\d{1,}',match_str)
re.findall('\D',match_str)
# \w 匹配一个包括下划线的单词字符
# \W 匹配一个非包括下划线的单词字符
re.findall('\w',match_str)
re.findall('\W',match_str)
# \s 匹配一个空白字符 如空格、制表符、换页符等
# \S 匹配一个非空白字符
match_str = '\r\t&a0b12c344d55&AC_ \n'
re.findall('\s',match_str)
re.findall('\S',match_str)

# 贪婪匹配
# 贪婪 倾向于最大长度匹配
# 非贪婪 倾向于最小长度匹配
match_str = 'lemon12banana34pear56'
re.findall('[a-z]{4,6}',match_str)  # ['lemon','banana','pear']
re.findall('[a-z]{4,6}?',match_str)  # ['lemo','bana','pear']

# 匹配次数
# * 代表匹配前面的字符零次或多次  {0,}
# + 代表匹配前面的字符一次或多次  {1,}
# ? 代表匹配前面的字符零次或一次  {0,1}
# 对于 ? 总结:
# 1. 如果数量词后面有 ?,该 ? 代表非贪婪的关键字,倾向于取最小长度匹配
# 2. 如果字符后面有 ?,该 ? 代表匹配前面字符 0次或1次

match_str = 'abcdef 123456 abcdef 456 abc'
re.findall('[a-z]{3,6}',match_str)  # ['abcdef','abcdef','abc']
# 定位符
# ^ 匹配字符串开始的位置
# $ 匹配字符串结束的位置
re.findall('^[a-z]{6}',match_str)  # ['abcdef']
re.findall('[a-z]{3}$',match_str)  # ['abc']

# 组的匹配
match_str = 'lemonlemonlemonappleapplepearpear'
re.findall('(lemon){3}',match_str)  # ['lemon']
re.search('(lemon){3}',match_str)  # <_sre.SRE_Matvh object; span(0,15),match='lemonlemonlemon'>
# 组 与 字符集 的区别
# (lemon)  匹配 lemon 这一组字符
# [lemon]  匹配 括号中的任意一个字母

# flags可选参数
match_str = 'lemon LEMON'
re.findall('lemon',match_str,re.I)  # ['lemon','LEMON']
# .  匹配除 “\n” 之外的任何单个字符
match_str = '\n123 abc\r'
re.findall('.',match_str,re.S)  # 使用 re.S 可以让 . 也匹配 \n
match_str = 'lemon\n LEMON\n'
re.findall('lemon.',match_str,re.I | re.S)  # ['lemon\n', 'LEMON\n']

# match search
match_str = 'a5678 lemon 1234'
re.findall('\d',match_str)  # ['5','6','7','8','1','2','3','4']
re.match('\d','5678 lemon 1234')  # <_sre.SRE_Match object; span=(0,1),match='5'>
re.search('\d',match_str)  # <_sre.SRE_Match object; span=(0,1),match='5'>
r = re.search('\d',match_str)  # <_sre.SRE_Match object; span=(0,1),match='5'>
r.group()  # '5'

# group 组的匹配
# match_str = 'lemonlemonlemonappleapplepearpear'
match_str = 'life is mostly happy,but sometimes sad'
# is mostly  cheerful,but sometimes
# is mostly cheerful  sometimes sad
r = re.search('life(.*)sad',match_str)
r  # <_sre.SRE_Match object; span=(0,38),match='life is mostly happy,but sometimes sad'>
r.group(0)  # life is mostly happy,but sometimes sad
r.group(1)  #  is mostly happy,but sometimes 
r1 = re.search('left(.*)but(.*)sad',match_str)
r1  # <_sre.SRE_Match object; span=(0,38),match='life is mostly happy,but sometimes sad'>
r1.group(1)  #  is mostly happy,
r1.group(2)  #  sometimes 
r1.group()  # (' is mostly happy,',' sometimes ')

# 正则替换
match_str = 'lemon apple 123456789 lemon lemon'
re.sub('lemon','a',match_str,count=0)  # 'a apple 123456789 a lemaon'
re.sub('lemon','a',match_str,count=1)  # 'a apple 123456789 lemon lemon'
re.sub('lemon','a',match_str,count=2)  # 'a apple 123456789 a lemon'
# 需求:数字小于 7 的,都转为 0,数字大于等于 7 的,都转为 10
def tranform(value):
  pass  # pass为站位操作
re.sub('\d',tranform,match_str,count=0)  # 'lemon apple  lemon lemon'
def tranform(value):
  print(value)
re.sub('\d',tranform,match_str,count=0)
# <_sre.SRE_Match object; span=(12,13),match='1'>
# <_sre.SRE_Match object; span=(13,14),match='2'>
# <_sre.SRE_Match object; span=(14,15),match='3'>
# <_sre.SRE_Match object; span=(15,16),match='4'>
# <_sre.SRE_Match object; span=(16,17),match='5'>
# <_sre.SRE_Match object; span=(17,18),match='6'>
# <_sre.SRE_Match object; span=(18,19),match='7'>
# <_sre.SRE_Match object; span=(19,20),match='8'>
# <_sre.SRE_Match object; span=(20,21),match='9'>
def tranform(value):
  match_num = value.group()
  print(match_num)
  if int(match_num) < 7:
    return '0'
  return '10'
re.sub('\d',tranform,match_str,count=0)  # 'lemon apple 000000101010 lemon lemon'

正则表达式全集:

字符描述
\将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\”匹配“\”而“(”则匹配“(”。
匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
*匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。
+匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
.匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用00…9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern)匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
(?<=pattern)反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
x|y匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。
[xyz]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz]负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。
[a-z]字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d匹配一个数字字符。等价于[0-9]。
\D匹配一个非数字字符。等价于[^0-9]。
\f匹配一个换页符。等价于\x0c和\cL。
\n匹配一个换行符。等价于\x0a和\cJ。
\r匹配一个回车符。等价于\x0d和\cM。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
\t匹配一个制表符。等价于\x09和\cI。
\v匹配一个垂直制表符。等价于\x0b和\cK。
\w匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”
\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”
\xn匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。.
\num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。

常用正则表达式

字符描述
用户名/^[a-z0-9_-]{3,16}$/
密码/^[a-z0-9_-]{6,18}$/
十六进制值/^#?([a-f0-9]{6}|[a-f0-9]{3})$/
电子邮箱/^([a-z0-9_.-]+)@([\da-z.-]+).([a-z.]{2,6})/或者/[az\d]+([˙az\d]+)@([\daz]([\daz])?)+(1,2˙[az]+)+/ 或者 /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+/
URL/^(https?://)?([\da-z.-]+).([a-z.]{2,6})([/\w .-])/?$/
IP 地址/((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/ 或者 /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
HTML 标签/^<([a-z]+)([^<]+)(?:>(.)</\1>|\s+/>)$/
删除代码\注释(?<!http:|\S)//.*$
Unicode编码中的汉字范围/^[\u2E80-\u9FFF]+$/

2.22 Pycharm

官网地址:www.jetbrains.com/pycharm/

download:

image.png

image.png

  • 运行 Pycharm 需要绑定 Python 解释器
  • 找到 Python 的安装路径,如:D:\tools\python\python.exe
  • 打开 PyCharm =》 打开项目 =》 File =》 Setting =》 Project: =》 Python Interpreter (Python解释器) =》 将Python的安装路径添加进去即可

2.23 Python 模块

  1. 基本组织结构

    包(文件夹) =》 模块(文件) =》 变量、for循环、while循环、def、class

    创建一个包:打开项目 =》 右键 =》 New =》 Python Package =》 例如:libs =》 会生成一个 libs文件夹,在libs文件夹下面会生成一个 init.py ,init.py 声明了 libs 是一个包,如果没有 init.py 则说明 libs 只是一个文件夹不是一个包。

在包里面可以创建很多模块,例如在 libs 下创建:p1.py、p2.py

image.png

  1. import 导入模块

p1.py、p2.py 两个模块在同一个包下面,根文件夹:右键 =》 Mark Directory as =》 Source Root libs/p1.py:

a = 1
b = 2
c = 3

libs/p2.py:

import p1
# import 模块名
print(p1.a,p1.b,p1.c)
# 也可以给p1取个别名: import p1 as t
# print(t.a,t.b,t.c)

跨包访问:

main.py:

import libs.p1 as t
print(p1.a)
print(p1.b)
print(p1.c)
  1. from import libs/p2.py:
from p1 import a,b,c
# from p1 import *
print(a)
print(b)
print(c)

main.py:

from libs.p1 import *
print(a)
print(b)
print(c)

设置哪些可以导入哪些不可以导入:

libs/p1.py:

__all__ = ['a','b']  # 这样在其他模块中就不能导入 c 了,只能导入 a、b
a = 1
b = 2
c = 3
  1. init.py
  • 声明一个文件夹为一个包
  • import 包 实际上导入的是这个包下面的 init.py
  • 该模块名为一个包名
  • 自定义选择哪些模块可以导入

libs/init.py:

print('This is libs.__init__.py')
print(__name__)  # libs
__all__ = ['p1']  # 自定义 libs 包下的p1模块可以呗导入,其他如p2不可被导入

main.py

import lib  # 导入的是 libs 下的 __init__.py
from libs import p1

libs/init.py:

__all__ = ['p1']  # 自定义 libs 包下的p1模块可以呗导入,其他如p2不可被导入

main.py

from libs import *
print(p1.a)
print(p2.a)  # 报错
  1. name libs/init.py:
print(__name__)

libs/p1.py:

def add(x,y):
  sum = x + y
  print(sum)
  return sum

# 只有从当前模块去运行才会执行,如果在其他模块导入当前模块则不执行
if __name__ == '__main__':
  add(3,4)

main.py

from libs.p1 import add
add(5,5)

2.24 迭代器、生成器、装饰器

  1. 迭代器
  • 迭代器:可以理解为一个容器,每次从容器中取出一个数据,直到数据被取完为止
  • 自定义迭代器:
    • 以类为例:需要在类中,实现两个方法 iternext 其中:
      1. iter 方法需要返回对象本身,它是for循环使用迭代器的要求;
      2. next 方法用于返回容器中下一个元素,当容器中的数据取完时,需要引发 StopIteration 异常。
# 需求:
# 1. 自定义迭代器,通过传入最小值最大值,返回该范围所有数值的3次方
# 2. 将返回的值,存入 num_list 列表中
class Number():
  def __init__(self,min,max):
    self.min = min
    self.max = max
  def __iter__(self):
    return self
  def __next__(self):
    # 返回这个范围内所有数值的3次方
    num = self.min
    if self.min <= self.max:
      self.min += 1
      return num **3
    else:
      raise StopIteration

for i in Number(1,5):
  print(i)

num_list = []
for i in Number(1,5):
  num_list.append(i)
num_list  # [1,8,27,64,125]
  1. 生成器

如果一个列表中,存有海量的数据,如果仅仅只是想访问其中某几个元素,那么这样的操作户特别耗内存;

  • 生成器特点:操作海量数据,节约大量内存空间
  • 生成器创建:
    • 函数中如果包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个生成器(generator)对象。
    • 在 Python 中,使用了 yield 的函数被称为生成器(generator)。
  • 运行特点:
    • 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
    • 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值,并在下一次执行 next() 方法时从当前位置继续运行。
# 创建一个生成器,掺入最大值最小值,执行 next() 方法
# 生成器一般都是跟函数搭配的
def mygene(min,max):
  while min < max:
    yield min
    min += 1

my_gene = mygene(1,5)
next(my_gene)
next(my_gene)
next(my_gene)


# yield 与 return 区别:
# return后,会跳出当前函数,yield 不会跳出当前函数
# yield 保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。
def test():
  return 1
  return 2

def genetest():
  yield 1
  yield 2

test = genetest()
next(test)
next(test)
  1. 闭包
# 闭包特点:(必需满足以下3个条件才是闭包函数)
# 1. 函数内部,再定义函数
# 2. 内部函数引用了外部变量但非全局变量
# 3. 需要把内部函数返回

def outer():
  a = 0
  def inner(b):
    print(a+b)
  return inner

f = outer()
f.__closure__[0].cell_contents  # 返回0; 返回 a 的值,则说明是闭包函数,否则不是闭包函数

def outer():
  a = 0
  def inner(b):
    print('')
  return inner

f = outer()
f.__closure__[0].cell_contents  # 报错,因为 内部函数并没有引用外部函数变量

# 如何修改闭包函数变量 a 的值
def outer():
  a = 0
  def inner(b):
    nonlocal a  # nonlocal 可以声明 a 不是当前函数的变量,而是上一级函数的变量
    a +=b
  return inner

f = outer()
f(10)
f.__closure__[0].cell_contents  # 10
f(30)
f.__closure__[0].cell_contents  # 40

# 闭包作用:
# 1. 定制装饰器
# 2. 并行运算
# ...
  1. 装饰器

装饰器是一种增加函数或类功能的简单方法,它可以快速地给不同的函数或类传入相同的功能。

调用被装饰的函数,与之前的调用过程没有任何的区别

def func():
  print('hello func')
def func1():
  print('hello func1')
# 需求:
# 给上面函数,加上两句打印
# print('开始执行')
# print('结束执行')
# 下面这种写法可以实现,但是效率低
def func():
  print('开始执行')
  print('hello func')
  print('结束执行')


# 装饰器基本格式
def decorate(func):  # 定义装饰器函数,参数为func,代表被装饰的函数,装饰器函数的名字可以自定义,不一定叫decorate,也可以命名为abc
  def wrapper(*args,**kwargs):  # 新定义一个包装函数,用于返回;名字可以自定义,不一定要命名为 wrapper
    print('执行开始')
    func(*args,**kwargs)  # 调用被装饰的函数
    print('执行结束')
  return wrapper  # 返回包装函数

# 使用
@decorate
def func():
  print('hello func')
func()
# 打印结果:
# 执行开始
# hello func
# 执行结束
@decorate
def func1():
  print('hello func1')
func1()
# 打印结果:
# 执行开始
# hello func1
# 执行结束

2.25 Python常见高级用法

  1. Lambda 匿名函数
# 匿名函数:没有定义函数的名称,可以实现函数某些简单功能
# 语法
lambda param_list:expression
# param_list:参数列表
# expression:建议书写一些简单的表达式,没法完整实现复杂代码块内容

# 需求
# 传入 x,y
# 返回 x+y 的值
f = lambda x,y:x+y  # 如果 x+y 改为 a=x+y 则会报错
f(3,4)  # 7

# 需求:
# 传入两个参数 x,y ,如果 x>=y 返回 x+y
# 如果 x < y , 返回 x-y
# 普通函数实现:
def f(x,y):
  if x>=y:
    return x+y
  return x-y
# 匿名函数与三元表达式搭配实现
f = lambda x,y: x+y if x>=y else x-y
f(3,4)  # -1
f(5,4)  # 9
  1. 三元表达式
# 三元表达式格式
# 条件为真的结果 if 条件判断 else 条件为假的结果

# 需求:
# 输入一个单词
# 如果是小写单词,则返回小写单词,否则都返回大写单词
f = lambda x: x if x.islower() else x.upper()
f('hello')
f('Hello')

  1. 高阶函数:map
# map 格式:
map(func, *iterables)
# func 代表可接收一个函数
# iterables 代表可接收一个或多个可迭代的序列


a = [1,2,3,4,5]
# 需求:
# 生成一个列表b,列表内的元素为a列表每个元素的三次方

b = []
for i in a:
  b.append(i ** 3)
b  # [1,8,27,64,125]

# 用map实现
def f(x):
  return x ** 3
b = map(f,a)
b  # <map at 0x1100eb1d0>
list(b)  # [1,8,27,64,125]

# 用 map 和 lambda 实现
b = map(lambda x:x**3,a)
list(b)  # [1,8,27,64,125]

# 需求:将两个列表元素相加之后结果,存放在一个新列表c中
a = [1,2,3,4,5]
b = [1,2,3,4,5]
c = map(lambda x,y:x+y,a,b)
list(c)  # [2,4,6,8,10]
# 长度不一样时
a = [1,2,3]
b = [1,2,3,4,5]
c = map(lambda x,y:x+y,a,b)
list(c)  # [2,4,6]

  1. reduce
# reduce 格式
from functools import reduce
reduce(function, sequence[, initial])
# function 接收一个函数
# sequence 接收一个可迭代序列
# initial 初始运算的值


a = [1,2,3,4,5]
# 需求:
# 计算a列表各元素相乘之后的值
num = reduce(lambda x,y:x*y,a)  # x、y会在a中寻找,最开始x是1,y是2,相乘以后为2;然后x是2,y是3,相乘以后为6;然后x是6,y是4,相乘以后是24,以此类推
num  # 120
num = reduce(lambda x,y:x*y,a,1000)  # 1000*1*2
num  # 120000

b = ['a','b','c']
r = reduce(lambda x,y:x+y,b)
r  # 'abc'
r = reduce(lambda x,y:x+y,b,'???')
r  # '???abc'

# 连续计算:计算a列表各元素相加之后的值



  1. filter
# filter 格式
filter(function, iterable)
# function 接收一个函数
# iterable 接收一个可迭代序列
# filter 返回结果必须是 True 或者 False
# 适用场景:用于序列元素过滤

a = [0,1,2,3,4,5]
# 需求:将 a列表中非0的元素,保存到b列表中
def f(x):
  if x!=0:
    return x
b = filter(f,a)
b  # <fiter at 0x10d96d080>
list(b)  # [1,2,3,4,5]

c = filter(lambda x:True if x!=0 else False,a)
list(c)  # [1,2,3,4,5]

c = filter(lambda x:x,a)
list(c)  # [1,2,3,4,5]
  1. 列表推导式
# 基本格式:
variable = [i for i in input_list if 条件判断]  # for i in input_list 是for循环,for i in input_list 中的i是一个循环变量名,每次遍历可迭代序列然后添加第一个变量i,if条件判断会对第一个i进行筛选
# variable 列表名,可自定义
# i 循环变量名
# input_list 可迭代序列
# if 条件判断,如果不写的话,默认所有条件都成立

# 需求:如何快速生成一个 0-9 列表
a = [i for i in range(10)]
a  # [0,1,2,3,4,5,6,7,8,9]
a = [i for i in range(10) if i>3]
a  # [4,5,6,7,8,9]

# 需求:生成一个列表,列表内的元素为a列表每个元素的三次方
a = [1,2,3,4,5]
# map lambda
b = map(lambda x:x**3,a)
list(b)  # [1,8,27,64,125]
c = [i**3 for i in a]
c  # [1,8,27,64,125]

# 需求:将字典里面的键,保存到一个列表c中
d = {'lemon':5,'apple':3,'pear':4}
c = [i for i in d.keys()]
c  # ['lemon','apple','pear']

# 扩展:将字典里的键与值,进行替换
e = {value:key for key,value in d.items()}
e  # {5:'lemon',3:'apple',4:'pear'}

2.26 文件和异常

  1. 文件读取
  • open函数
    • open(file, mode='r',buffering=-1,encoding=None, errors=None, newline=None, closefd=True, opener=None)
    • 参数说明:
      • file:必需,文件路径(相对或绝对路径)
      • mode:可选,文件打开模式
      • encoding:一般使用utf-8
      • buffering:设置缓冲
      • errors:报错级别
      • newline:区分换行符
      • closefd:传入的file参数类型
    • mode 常用参数:
      • r : 以只读方式打开文件
      • w : 以只写方式打开文件
        • 如果改文件不存在,创建新文件
        • 如果改文件已存在,则覆盖原文件
      • a : 打开一个文件用于追加
        • 如果改文件已存在,则在最尾处追加写入
        • 如果改文件不存在,创建新文件进行写入
      • 更多mode参数说明,可访问:www.runoob.com/python/file…

files/文本.txt

Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。
Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
Python 是由 Guido van Rossum 在八十年代末和九十年代初,在荷兰国家数学和计算机科学研究所设计出来的。
Python 本身也是由诸多其他语言发展而来的,这包括 ABC、Modula-3、C、C++、Algol-68、SmallTalk、Unix shell 和其他的脚本语言等等。
像 Perl 语言一样,Python 源代码同样遵循 GPL(GNU General Public License)协议。
现在 Python 是由一个核心开发团队在维护,Guido van Rossum 仍然占据着至关重要的作用,指导其进展。
Python 2.7 被确定为最后一个 Python 2.x 版本,它除了支持 Python 2.x 语法外,还支持部分 Python 3.1 语法。

main.py

# 实现简单的文件读取操作
# 文件的路径也可以用相对路径:files/文本.txt
f = open('文本.txt 的绝对路径',mode='r',encoding='utf-8')
data = f.read()
print(data)
f.close()  # 用open打开要用close将文件关闭

# 为避免忘记close文件,可以用一下方式读取文件
with open('files/文本.txt',mode='r',encoding='utf-8') as f:  # 用变量f来接收
  data = f.read()
  print(data)

  1. 文件的读取格式
  • with open(file='file_path',mode='r',encoding='utf-8') as f:
    • data = f.read() # 返回整个文件数据,如果文件较大,不建议用这种方法
    • data1 = f.readline() # 返回一行数据
    • data2 = f.readlines() # 以列表格式,返回整个文件数据
  1. 文件的写入格式
  • with open(file='file_path',mode='w',encoding='utf-8') as f:
    • file.write(str) # 将字符串写入文件
    • file.writeline(sequence) # 向文件写入一个序列字符串列表,如果需要换行则要自己加入换行符
  1. 文件的写入
with open('files/文本.txt',mode='w',encoding='utf-8') as f:
  #f.write('hello lemon\n hello world')
  f.writelines(['hello pycharm\n','hello apple\n','hello'])

with open('files/文本.txt',mode='a',encoding='utf-8') as f:
  f.write('hello lemon\n hello world')
  f.writelines(['hello pycharm\n','hello apple\n','hello'])
  1. JSON与文件读写
  • (1)JSON(JavaScript Object Notation)特点:

    • 1)JSON 是一种轻量级的数据交换格式,易于人阅读和编写
    • 2)JSON 具有通用性,支持几乎所有的语言
    • 3)JSON 支持跨平台,支持 windows,Linux,Mac平台
  • (2)常用JSON函数

    • 1)json.dumps 将 Python 对象编码成 JSON 字符串
    • 2)json.loads 将 已编码的 JSON 字符串解码为 Python 对象
    • 3)json.dump 将 JSON 字符串数据写进文件
    • 4)json.load 读取 JSON 文件里面的数据
    • 5)python
      • {'python':1,'Java':2,'Hadoop':3}
      • {"python":1,"Java":2,"Hadoop":3}
    • 6)JSON
      • '{"python":1,"Java":2,"Hadoop":3}'
  • (3)Python 与 JSON 类型转换

    PythonJSON
    dictobject
    list, tuplearray
    strstring
    int, floatnumber
    Truetrue
    Falsefalse
    Nonenull
    第一列文本居中第二列文本居右
import json

def f1():
  '''
  对Python对象进行操作
  '''

  # json.dumps
  # 将 Python 对象编码成 JSON 字符串
  p_list = [
    {'lemon':True,'apple':6},
    {'pear':6,'banana':False},
  ]
  p_dict = {'python':1,'Java':2,'Hadoop':None}
  json_list = json.dumps(p_list)
  json_dict = json.dumps(p_dict)



  # json.loads
  # 将已编码的 JSON 字符串解码为 Python 对象
  list1 = json.loads(json_list)
  dict1 = json.loads(json_dict)



def f2():
  '''
  文件的读写
  '''

  # 写入JSON文件
  p_dict = '{"python":1,"Java":2,"hadoop":null,"lemon":true,"banana":false}'

  with open('files/json_test.json','w',encoding='utf-8') as f:
    json.dump(p_dict,f)


  # 读取JSON文件
  with open('files/json_test.json','r',encoding='utf-8') as f:
    data = json.load(f)
    data1 = json.loads(data)
    print(data)
    print(data1)



if __name__ == '__main__':
  f2()
  1. try-except-finally捕捉异常
  • (1)什么是异常:
    • 1)异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
    • 2)一般情况下,在Python无法正常处理程序时就会发生一个异常
    • 3)异常是Python对象,表示一个错误
    • 4)当Python脚本发生异常时我们需要捕获处理,否则程序会终止执行
  • (2)捕获异常的基本格式
    try:
      语句一  # 检测语句一是否存在错误
    
    except 异常名称:
      语句二  # 若语句一存在错误,可以捕获错误
    
    finally:
      语句三  # 无论是否存在错误,都会执行finally内代码
      
    
  • (3)常见异常名称
    • BaseException: 所有异常错误
    • Exception: 常规异常错误
    • ZeroDivisionError: 除0异常错误
    • ValueError: 值类型异常错误
    • 更多异常错误,可查看:www.runoob.com/python/pyth…

exception_demo.py

def f(num):
  try:
    num / 0
  except ZeroDivisionError as e:
    print(e)
  finally:
    print('执行结束')

def f1(num):
  try:
    return int(num)
  except ValueError as e:
    print(e)
  finally:
    print('执行结束')

# 同时捕获多个异常
def f2(num):
  try:
    return int(num)
  except ZeroDivisionError as e:
    print(e)
  except ValueError as e:
    print(e)
  finally:
    print('执行结束')

# 同时捕获多个异常简写
def f3(num):
  try:
    return int(num)
  except (ZeroDivisionError,ValueError) as e:
    print(e)
  finally:
    print('执行结束')

def f4(num):
  try:
    return int(num)
  except BaseException as e:
    print(e)
  finally:
    print('执行结束')

if __name__ == '__main__':
  # f(1)
  f1(a)
  1. raise 与 asert
  • (1)raise 抛出异常
    • 除了使用 try-except-finally 格式来捕获异常
    • 也可以通过 raise 显示的引发异常
    • 一旦引发 raise 后面的异常,将终止程序运行
  • (2)assert 断言
    • assert 的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题
    • 基本格式:
      • assert expression [,arguments]
    • 如果 bool_expression 为 False,则会抛出 arguments 这个自定义异常信息
    • 如果 bool_expression 为 True,则不会抛出 arguments 这个自定义异常信息
# 需求1:
# 1. 传入一个参数,判断是否为整型类型,如果不是,则抛出异常,终止程序
# 2. 判断是否大于等于5,如果小于5,则抛出异常,终止程序
def f2(num):
  # if not isinstance(num,int):
  #   raise Exception('该参数不是一个整型类型')
  # if num < 5:
  #   raise Exception('该参数小于5')

  assert isinstance(num,int),'该参数不是一个整型类型'
  assert num>=5,'该参数小于5'

if __name__ == '__main__':
  f2('a')

# 需求2:
# 传入若干个参数,判断参数个数如果小于等于5,则抛出异常,终止程序
def f3(*args):
  # if len(args)<=5:
  #   raise Exception('参数个数小于等于5个')

  assert len(args)>5,'该参数个数小于等于5'

if __name__ == '__main__':
  f3(1,2,3,4,5)

2.27 虚拟环境

  1. 为什么要搭建虚拟环境
  项目A需要运行在Python2环境下,项目B需要运行在Python3环境下。
  项目A和项目B,使用同一个包,但是项目A需要使用该包的1.0版本,项目B需要使用该包的2.0版本
  那么创建虚拟环境,可以解决包管理的问题
  1. 搭建虚拟环境
  pip install pipenv
  创建一个文件夹
  pipenv --three    会使用当前系统的Python3创建环境
  pipenv shell      激活虚拟环境
  pipenv --py       显示Python解释器信息
  exit              退出当前的虚拟环境
  1. pipenv 常见操作
  (1)包下载
    下载包之前,将国外下载源,更改为国内源
    url = "https://pypi.tuna.tsinghua.edu.cn/simple"
    修改下载源在 Pipfile 文件中修改
    pipenv install requests
    pipenv install requests--2.21.0
  (2)查看当前下载包情况
    pip list
  (3)查看当前包依赖情况
    pipenv graph
  (4)更新包
    pipenv update requests  # 更新requests
    pipenv update           # 更新所有包
  (5)卸载包
    pipenv uninstall requests # 卸载requests包
    pipenv uninstall --all    # 卸载全部包并从Pipfile中移除
  (6)其他操作
    pipenv check  # 检查安全漏洞

2.28 简单爬虫实战

  1. HTML简单介绍
超文本标记语言(HyperText Markup Language),是网页制作必备的变成语言。
超文本,可以包含文字、图片、链接,甚至音乐、程序等元素

超文本标记语言的结构包括“头”部分(英语:Head)、和“主体”部分(英语:Body)
其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容

基本格式:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
</body>
</html>
  1. XPath获取数据 XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。

    常用路径表达式:

    表达式描述
    /从根节点选取
    //从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
    @选取属性

files/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>这是一级标题</h1>
  <h2>这是二级标题</h2>
  <p>这是一段文字</p>
  <img src="视频水印.png">
  <div>
    <ul>hello lemon</ul>
    <ul>hello world</ul>
  </div>

  <h3>这是三级标题</h3>
  <div id="list">
    <p>python</p>
    <p>Java</p>
    <p class="Hadoop">Hadoop</p>
  </div>
</body>
</html>

xpath_demo.py

from lxml.html import fromstring
# fromstring 可以将字符串类型转换为html格式

with open('files/index.html','r',encoding='utf-8') as f:
  data = f.read()
  print(data)
  print(type(data))   # <class 'str'>

selector = fromstring(data)
print(type(selector))   # <class 'lxml.html.HtmlElement'>
h1 = selector.xpath('/html/body/h1/text()')[0]
h1 = selector.xpath('//h1/text()')[0]
p = selector.xpath('/html/body/p/text()')[0]
p = selector.xpath('//body/p/text()')[0]
div_ul = selector.xpath('//div/ul/text()')
div_p = selector.xpath('//div/p/text()')
div_p = selector.xpath('//div[@id="list"]/p/text()')
div_p = selector.xpath('//div[@id="list"]/p[last()]/text()')
div_p = selector.xpath('//div[@id="list"]/p[@class="Hadoop"]/text()')
  1. 爬虫原则
  • (1)明确爬取的内容
  • (2)分析网页结构,找到目标的标签
  • (3)分析目标标签,获取目标数据
  • (4)数据入库
  1. 简单爬虫实战
(1)明确爬取的内容
  正在上映的电影
(2)分析网页结构,找到目标的标签
  div[@id="nowplaying"]/div[@class="mod-bd"]/ul/li
(3)分析目标标签,获取目标数据
  电影名称、电影评分、电影评分人数
  电影时长、上映年份、地区、导演、主要演员
(4)数据入库
  写入到json文件里面
  1. 断点调试
  Mac:      fn + f6   单步调试
            fn + f8   跳到下一个断点
  Window:   f6   单步调试
            f8   跳到下一个断点
import requests   # requests 这个包的将目标网站拉取下来
from lxml.html import fromstring
import json

class SpiderDouban():
  def __init__(self,url):
    self.url = url
    self.header = {
      'Accept': '',
      'Accept-Encoding': '',
      'Accept-Language': '',
      'Host': '',
      'Referer': '',
      'User-Agent': '',
      '': '',
    }
  def get_data(self):
    r = requests.get(url=self.url,headers=self.headers)
    data = fromstring(r.text)
    selector = data.xpath('//div[@id="nowplaying"]/div[@class="mod-bd"]/ul/li')
    for i in selector:
      title = i.xpath('@data-title')
      score = i.xpath('@data-score')
      votecount = i.xpath('@data-votecount')
      duration = i.xpath('@data-duration')
      ralease = i.xpath('@data-ralease')
      region = i.xpath('@data-region')
      director = i.xpath('@data-director')
      actors = i.xpath('@data-actors')

      print(title)

      movie_data.append({
        'title': title if title else '',
        'score': score if score else '',
        'votecount': votecount if votecount else '',
        'duration': duration if duration else '',
        'ralease': ralease if ralease else '',
        'region': region if region else '',
        'director': director if director else '',
        'actors': actors if actors else '',
      })
    with open('files/movie_data.json','w',encoding='utf-8') as f:
      json.dump(movie_data,f,indent=1,ensure_ascii=False)

if __name__ == '__main__':
  s = SpiderDouban('https://movie.douban.com/...')
  s.get_data()

3 Python 可深入的方向

爬虫工程师:
  相关爬虫工具:Scrapy 爬虫框架、Selerium
  反爬策略(ip代理池、随机更换 User-Agent、Cookie禁用、自动限速等方法)
  数据库知识(如:Mysql  Oracle 等)
Web开发工程师:
  相关框架:Django Flask
  前端知识:JavaScript CSS HTML
  数据库知识
数据分析师:
  初级数据分析:
    数据库相关知识:Mysql  Oracle  MongoDB  Redis
  中高级数据分析:
    Python 数据科学常见包:Numpy  Pandas  Matplotlib  Scipy
    统计学知识:线性代数
    机器学习常见算法:线性回归法、梯度下降法、PCA、SW、决策树、随机森林等
大数据方向:
  相关工具:Spark  Hadoop
  其他语言基础:Java SE
  Linux 相关知识
人工智能方向:
  相关框架:TensorFlow (一个完全开源的人工智能框架)、Keras
  相关工具:Matplotlib 、 Numpy、TensorBoard
  Linux 相关知识