参考资料备用:
python ABC
3.8.2Documentation
python cookbook 3rd
pip安装超时解决办法

vscode小技巧

  • 打开命令窗口:Ctrl+`
  • 注释:单行 – Ctrl+/,多行 – Shift+Alt+A
  • cmd:cls清屏
  • Ctrl + Shift + O:快速定位函数

目录速查

Python入门导学
Python基本类型:数字,字符串
组:列表,元组,集合,字典
变量与运算符
分支、循环、条件和枚举
包、模块、类
函数
面向对象:类,实例,方法,继承
正则表达式和JSON
枚举类型,闭包
匿名函数、高阶函数、装饰器
爬虫实战
Python杂记

Python入门导学

返回

特点

  • 简洁;丰富的标准库和第三方库(电子邮件、GUI);面向对象+函数式编程;易于上手,难于精通;既有动态脚本的特性,又有面向对象的特性。
  • 豆瓣、知乎
  • Simple is better than complex.
    Now is better than never. Although never is often better than an right now.
  • 缺点:慢
    编译型语言(C、C++)–运行效率
    解释型语言(Javascript,Python)–开发效率

一个经典误区:编程 = web编程?

  • 世界上不是只有网站,还有很多问题需要编程来解决。
  • web是基础–爬虫、数据服务提供、数据分析。
  • 互联网时代,有网络的地方就需要web。
  • web编程确实是最好的语言实践–业务逻辑思考能力、宽广的知识面。

Python能做什么

  • 爬虫
  • 大数据与数据分析(Spark)
  • 自动化运维与自动化测试
  • web开发:Flask,Django
  • 机器学习:Tensor Flow(谷歌)
  • 胶水语言:能够把其他语言制作的各种模块(尤其是C/C++)轻松地联结在一起

正确打开方式:遇到问题时,随手拿起Python写个工具

什么是写代码&Python的基本类型

返回

什么是代码,什么是写代码

  • 代码: 现实世界事物在计算机世界中的映射
  • 写代码: 将现实世界中的事物用计算机语言来描述

数字

整型与浮点型

  • 整数:int
    其他语言有shortintlong
  • 浮点数:float
    其他语言有单双精度之分,Python没有

type(2/2)float(1.0),type(2//2)int(1)
*双斜杠是“整除”

10、2、8、16进制&表示&转换

  • 其他进制:60s = 1min
  • 2进制:0b10,直接在IDLE回车就会返回2
    8进制:0o10 = 8
    16进制:0x10 = 16
  • bin():将其他进制转换成2进制
    oct():将其他进制转换成8进制
    hex():将其他进制转换成16进制
    int():将其他进制转换成10进制

布尔类型和复数(属于数字分类)

  • bool:表示真、假
    True/False,要大写
    只要非 0/空串/空列表/None,就都是True
  • complex:复数(36j
    抓大放小,抓住重点深入

字符串str

单双引号

  • 单引号和双引号–成对出现
    "let's go"'let\'s go'

多行字符串

  • 一行79,回车字符\n会读进字符串中
'''
hello world
hello world
'''
"""
hello world
hello world
"""
  • IDLE写'\n'输出还是'\n',不换行
    print("""hello world\nhello world\n""")会输出换行
  • 单引号换行:
'hello\
world'

输出'helloworld'

转义字符–特殊的字符

  • 表示无法“看见”的字符
  • 与本身语法有冲突的字符
  • \n换行
    \r回车:光标回到本行首位置,不会换行
    \t横向制表符:TAB
    \'单引号

原始字符串

  • 字符串前加r/R,原始字符串–所看即所得。
  • 'let's go'无法通过加r解决–引号要成对出现

字符串运算

  • +:拼接
    *数字:重复数字倍
  • 获取单个字符:“字符串”[i],负数从后往前数
    获取一段字符:步长
    'hello world'[0:4]输出'hell'要读到字符下一位
    'hello world'[0:-1]输出'hello worl'
  • 怎么输出world?
    "hello world"[6:],默认取字符串最后一位
    "hello world"[-5:],后往前数第5位,到末尾

“组”的概念与定义

返回

列表list

定义

列表内部可以存放不同类型元素
列表内部可以嵌套列表

基本操作

  • 取元素
["新月打击","苍白之瀑","月之降临","月神冲刺"][0]
'新月打击'    #返回的是元素
["新月打击","苍白之瀑","月之降临","月神冲刺"][-1:]
['月神冲刺']  #返回的是列表
  • 合并列表:+
  • *3:把列表内元素重复三次

元组tuple

  • 同列表
  • type(('hello'))返回值str:为什么只有一个元素的元组是元素的类型?
    答:()内只有一个元素,python优先认为()是数学运算符,返回数学运(比如(1))。
    表示只有一个元素的元组:(1,)
    表示一个元素都没有的空元组:()
    type([1])返回值是list

序列总结

  • 序号
  • 切片
    "hello world"[0:8:2]返回'hlow–在0-7的切片内隔1取元素?
  • +*
  • 元素是否在序列中:innot in,返回bool值
    3 in [1,2,3,4,5]返回True
  • len()max()min():返回序列长度、最大值、最小值
    max、min不支持不同类型元素比较
  • ord()返回单个字符的ASC码(字符串不行)

集合set

  • 最大的特点——无序
    {1,2,3,4,5}不支持序号、切片
  • 不重复
    {1,1,1,2,2,3,4,5}返回{1,2,3,4,5}
  • len()
    innot in
  • {1,2,3,4,5,6} - {3,4}:两个集合取差集
    {1,2,3,4,5,6} & {3,4}:两个集合取交集
    {1,2,3,4,5,6} | {3,4,7}:两个集合取并集
  • 怎么定义空的集合?
    type({})返回dict类型 – 不可用
    type(set())返回set类型 – 正确操作

字典dict

  • 很多的keyvalueset的延生而不是序列的
    {key1:value, key2:value, ……}
  • 最常用操作:通过key得到/访问value
  • key值不可重复
{'Q':"新月打击",'W':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}['Q']
'新月打击'
{'Q':"新月打击",'Q':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}['Q']
'苍白之瀑'
{'Q':"新月打击",'Q':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}
{'Q':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}
  • value类型无限制,可以也是一个字典
    key必须是不可变的类型 – 字符串和元组不可变,列表可变

变量与运算符

返回

变量

什么是变量

  • 名字:起名字要有意义 – 命名可读性要强,多查单词
  • =:赋值符号

命名规则

  • 字母、数字、下划线
  • 首位不能是数字
  • 系统关键字(保留关键字)不能用在变量名中
    非保留的也尽量不要用,血和泪的教训。
type = 1
type(1) #报错,此时等价于1(1)

值类型与引用类型

a = 1
b = a
a = 3      #a指向了新的int(3)
print(b)        #1a = [1,2,3,4,5]
b = a
a[0] = '1'   #a没有指向新的list,而是改变原来的list
print(b)        #['1',2,3,4,5]
  • 值类型:不可改变
    intstrtuple
    引用类型:可改变
    listsetdict
#str不可变,id()得到地址,发现前后地址变了,说明不是在原地址上修改
b = 'hello'
b = b + 'python'    #生成新的字符串,再赋值给b
print(b)    #hellopython
  • listtuple
    元组不可修改,能用元组就用元组 – 代码稳定性考虑
a = (1,2,3,[1,2,['a','b','c']])
a[2] = '3'   #不可改变,报错
a[3][2][1] = '4' #可以改变,变为(1,2,3,[1,2,['a','4','c']])

运算符

算术运算符

+-*///整除,%**指数(2**5 = 32

赋值运算符

  • 先做运算再赋值
  • python中没有自增自减运算

比较运算符

  • 返回一个bool

逻辑运算符

  • 与、或、非
  • intfloat0被认为是False
    字符串中空字符串""是False
    列表中空的列表[]被认为是False
  • andor 的返回值 – 最后一个读到的内容
    1 and 2返回2,2 and 1返回1 – 读到第二个数字才能判断
    1 or 2返回1 – 读到第一个1的时候就能判断了

成员运算符

  • innot in
  • 字典类型判断的是key

身份运算符

  • isis not– 两个变量的身份是否相等
a = 1
b = 1.0
a == b        #True
a is b      #False
  • id()查看他们的地址,地址相同身份相同 – is比较的是地址
a = {1,2,3}
b = {2,1,3}
a == b        #True, set无序
a is b      #False, 地址不同

判断变量的值、身份、类型 – 对象3特征

  • ==
    is身份
    isinstance(a, int)类型
  • isinstance(a, (int, str, float)) a是否是元组里三个类型中的一个,是返回True,否返回False

位运算符

b = 3
bin(b)      #'0b11',3
bin(~b)     #'-0b100',前面取负末位+1,-4
a = 2
bin(a)      #'0b10'
bin(a<<1) #'0b100'
bin(a>>3) #'0b0'

分支、循环、条件和枚举

返回

表达式

什么是表达式

表达式是运算符和操作数组成的序列

表达式优先级

  • 一般右结合,出现=左结合,与运算符优先级无关
  • 运算符优先级最高,然后是比较,逻辑运算符最低:not > and > or
  • 加辅助括号可以改变运算顺序

流程控制语句

条件控制

if d:a = input()    #读入的是字符串pass    #空语句,占位语句
elif:pass
else:pass

pylint规范

  • python中实际没有常量,用大写
  • 每个模块开头一段注释,说明
  • tab 四个空格、切换到下一个代码编辑区域
  • python没有switch
    elif代替,或者字典处理
  • a,b不同时为False:a or b

循环

while的循环场景

  • 递归
counter = 1
while counter <= 10:counter += 1print(counter)
else:print('EOF') #循环结束的时候执行else

for

for target_list in expression_list:pass
else:pass   #列表全部打完以后执行else,强制break结束时不会执行else
  • range
for x in range(0, 10, 2):    #范围,步长pass
for x in range(10, 0, -2):printf(x, end=' | ')一定要用for吗?
a = [1,2,3,4,5,6,7,8]
for i in range(0, len(a), 2):print(a[i], end=' | ')
b = a[0:len(a):2]
print(b)

python的组织结构-包、模块、类

返回

  • 包(文件夹,包含__init__.py),模块,类(用类把函数、变量组织起来)
    包.模块seven.c4,子包
  • __init__.py的模块名就是包的名字

导入

import c7    #同级,导入模块
print(c7.a)import t.c7  #子包中
print(t.c7.a)from t.c7 import a, def    #导入变量、函数
print(a)from t import c7    #导入模块
print(c7.a)from t.c7 import *   #导入所有变量和函数,能不用就不用
__all__ = ['a', 'c']
#在模块开头,改变*关于全部的定义
#模块的内置属性#末尾加反斜杠可以换行, ()也可以换行
from c7 import a, b\
c
from c7 import (a, b
c)

init.py

  • 导入包时自动运行:
    无论是导入包还是导入包下面的模块,都会自动运行__init__.py
  • __init__.py内设置__all__可以控制*时导入的包内模块
  • 批量导入包
  • 注意点:
    ① 包和模块不会被重复导入
    ② 避免循环导入
    ③ python导入模块时会执行所导入模块的代码

模块内置变量

  • dir()返回当前模块的变量列表
    dir(sys)返回指定模块sys的变量列表
  • 错误信息:堆栈信息(路径)+详细信息(原因)
  • __doc__存放模块注释信息
    __file__存放文件路径

入口文件和普通模块内置变量的区别

print('package: ' + (__package__ or 当前模块不属于任何包))  #当前模块不属于任何包
print('name: ' + __name__)   #__main__
print('doc: ' + (__package__ or 当前模块没有文档注释))
print('file: ' + __file__)   #文件名c9.py

__name__的经典应用

if __name == '__main__':pass #作为可执行文件时才会执行
#Make a script both importable and executabl
  • python -m seven.c15把c15按模块执行,命名空间(?)
    python seven\c15.py路径方式

相对导入和绝对导入

  • 决定顶级包的是可执行文件
    package2.package4,demo不是顶级包
  • 绝对导入必须从顶级包开始
  • 相对路径:
    .表示当前目录
    …表示上层目录
    …表示上上层目录
  • 入口文件不能使用相对路径
    因为入口文件的__name__被设置成__main__无法作为路径使用
    一定要在路口文件使用相对路径:
    回到demo的上一级,python -m demo.main,此时相对导入可用,输出demo.package2.package4
  • 相对导入
from .m3 import m
from ...m5 import m
# attempted relative import beyond top-level package

Python 函数

返回

函数

  • round(a, 2)保留小数点后两位,同时四舍五入
  • help(round)查看内置函数
  • import this打印python之禅
  • 特点:功能性、隐藏细节、避免编写重复的代码

函数的定义和运行特点

def funcname(parameter_list):pass
#1. 参数列表可以没有
#2. return value None
  • [Previous line repeated 995 more times]递归超过995次
import sys
sys.setrecursionlimit(100)
#设置最大递归层数
#[Previous line repeated 95 more times]

返回多个结果

def damage(skill1, skill2):damage1 = skill1 * 3damage2 = skill2 * 2return damage1, damage2skill1_damage, skill2_damage = damage(3, 4)
#用两个变量(有意义的变量名)存放两个返回值
#序列解包

序列解包

d = 1, 2, 3
print(type(d))  #tuplea, b, c = d      #序列解包
a, b = [1, 2, 3]   #报错,用两个变量接收三个值a=b=c=1     #连续赋值√

参数

必须参数与关键字参数

  • 必须参数:
    c = add(3, 2)
  • 关键字参数:
    c = add(y=3, x=2),不用固定实参的输入顺序
  • 备注:
    二者的差别在函数的调用上,不在定义上
    ② 定义了多少形参就要传入多少实参

默认参数

  • 定义的时候给形参默认值
  • 调用时正常传递实参即可按顺序覆盖,没有默认值的形参必须传入实参
  • 必须传入的参数必须放在默认参数前面
  • print_student('lxxx', age=17)可以不按参数列表顺序传入改变默认值
  • 默认值参数和必须参数不能混着调用
    print_student('lxxx', gender='nv', 17, college='xx')

可变参数/形参列表可变

def demo(*param):print(param)    print(type(param))  #tupledemo(1,2,3,4,5,6)a = (1,2,3,4,5)
demo(a)     #报错,传递进入的是一个元组
demo(*a)    #√ 类似解包,传入的是可变参数def demo(param1, param2=2, *param):print(param1)    print(param2)print(param)demo('a', 1,2,3)
#a
#1  默认值参数在前,读完才读可变参数
#(2,3)def demo(param1, *param, param2=2):print(param1) print(param2)print(param)demo('a', 1,2,3, 'param')
#a
#(1,2,3,'param')  可变参数会把剩余全部传入可变
#2demo('a', 1,2,3, param2='param')
#a
#(1,2,3)
#param

尽量保证形参列表的简单

关键字可变参数/任意个数的关键字参数

def city_temp(**param)print(type(param)) #dictfor key,value in param.items():print(key, ':', value)print(param)a = {'bj':'32c', 'sh':'31c'}
city_temp(**a)
city_temp()     #{}

作用域

变量作用域

c = 50  #全局变量
def demo():c = 10  #局部变量print(c)   #10def demo1():print(c) #50demo()
print(c)    #50def demo2():for i in range(0,9):a += iptint(a) #python没有块级变量的概念

作用域链

c = 1
def func1():c = 2def func2():c = 3print(c)func1()     #3 2 1

global关键字

def demo():global cc = 2demo()
print(c)
  • 全局变量在整个程序里面都能用

小作业1-合成石头划算不

要求




代码

  • stone.py
'''
this is about class stone
'''class Stone():level = 1value = 0l1_diamond = 8l1_value = 0.75up_num = 12up_gold = 0.39up_vit = 10up_rate = 1def l1_to_l3(self):self.value += 13*self.l1_valueself.value += 13*self.l1_diamond*0.05self.value += self.up_goldself.value += self.up_vit*1self.level = 3self.up_gold = 0.897self.up_vit = 10self.up_rate = 0.4878def l3_to_l4(self):temp_sum = 0temp_sum += 16*self.l1_valuetemp_sum += 16*self.l1_diamond*0.05temp_sum += self.up_goldtemp_sum += self.up_vit*1self.value += temp_sum*self.up_ratetemp_sum = 0temp_sum += 16*self.l1_valuetemp_sum += 16*self.l1_diamond*0.05temp_sum += self.up_goldself.value += temp_sum*(1-self.up_rate)self.level = 4self.up_gold = 19.75self.up_vit = 10self.up_rate = 1def l4_to_l6(self):self.value += 12*self.valueself.value += self.up_goldself.value += self.up_vit*1
  • main.py
from stone import Stones1 = Stone()
s1.l1_to_l3()
s1.l3_to_l4()
s1.l4_to_l6()
composite_value = s1.value
buy_value = 750
print('composite value is ' + str(composite_value))
if composite_value<buy_value:print('It\'s more cost-effective to synthesize yourself.')
else:print('Buying directly is more cost-effective.')

结果

面向对象

返回

  • 有意义的面向对象的代码

定义

  • 首字母大写,不要用下划线连接
  • 类只负责描述定义,不负责执行=类内不能运行调用这个类
    一个模块专门用来定义类,调用写进另外的模块
  • 类最基本的作用:封装
class Student(): name = ''age = 0def print_file(self):   #即使不需要调用任何参数还是要在定义的时候加入selfprint('name:' + self.name)print('age:' + str(self.age))#实例化
student = Student()
student.print_file()    #调用类下面的方法
  • 方法与函数的区别
    方法:设计层面
    函数:程序运行的过程式

类和对象的关系

  • 实例化
  • 类的设计:行为与特征
  • 类是模板,可以产生很多不同的对象

构造函数

  • 实例化的过程中会自动调用构造函数,一般不显示调用构造函数
  • 构造函数不能返回除了None以外的值(也不是用来返回什么东西的)
  • 构造函数的作用,让模板生成不同的对象

类变量、实例变量、self

class Student():name = 'qiyue'    #类变量age = 0def __init__(self, name, age):  #添加参数以后必须要传入参数self.name = name self.age = ageprint('student')   #实例变量student1 = Student('石敢当', 18)
student2 = Student()   #报错
print(student1.name)    #石敢当
print(Sturent.name)     #qiyue
  • 为什么要写self,显胜于隐

实例方法、类方法、静态方法

  • 实例方法:def do_homework(self):
    实例可以调用的方法,操作实例变量
  • 在实例方法里面访问类变量
print(Student.sum1)
print(self.__class__.sum1)

不能直接用变量名访问类变量

'''
实例方法调用类变量
'''
class Student():name = ''age = 0sum_s = 0def __init__(self, name, age)self.name = nameself.age = age#self.__class__.sum_s += 1#print('当前学生总数为:' + str(self.__class__.sum_s))'''
定义类方法
'''@classmethoddef plus_sum(cls)cls.sum_s += 1print(cls.sum_s)'''
定义静态方法
'''@staticmethoddef add(x,y):print('This is a static method')s1 = Student('石敢当', 18)   #当前学生总数为:1
Student.plus_sum()
s2 = Student('喜小乐', 16)  #当前学生总数为:2
Student.plus_sum()
s1.plus_sum()   #python中实例对象可以调用类方法,但是不建议这么干!
s1.add(1,2)
Student.add(1,2)
  • 静态方法和面向对象关系很弱,像一个普通函数,一般不推荐使用

成员可见性

  • 成员:变量和方法
  • 类有内外之分
 def do_homework(self):self.do_english_homework()    #内部调用print('homework')def do_english_homework(self):print('english homework')s1 = Student('石敢当', 18)
s1.do_homework()    #外部调用
  • 提倡的规范:
    所有类下变量的更改都通过方法操作(对数据保护,避免不规范操作)

公开和私有

  • 公开的 public:可以在外部直接调用
    私有的 private:外部无法直接读取/设置
  • python怎么判断公开还是私有?
    方法在开头加双下划线__,变为私有
    为什么__init__可以在外部调用?因为它后面也有下划线!这是python内置函数的命名风格

没有什么是不可以访问的!

s1 = Student('石敢当', 18)
s2 = Student('喜小乐', 16)
s1.__score = -1        #给实例对象创建了一个新的属性并赋值,不是给私有成员赋值
print(s1.__score)   #-1
print(s2.__score)   #报错
print(s1.__dict__)  #打印变量
#{'name':'石敢当', 'age':18, '_Student__score':59, '__score':-1}
print(s1._Student__score)   #成功读取!但是没什么意义不建议这么玩

面向对象三大特性

  • 继承性、封装性(抽象程度高)、多态性

继承性

  • 避免定义重复的方法、重复的变量
from c6 import Human
'''
class Human():sum = 0def __init__(self, name, age):self.name = nameself.age = agedef get_name(self):print(self.name)
'''
class Student(Human):passprint(Student.sum)     #0,从Human里面继承的
s1 = Student('石敢当', 18)
print(s1.name)      #以下都可以继承
print(s1.age)
s1.getname()

  • 单继承。Python允许多继承,单继承都没用好请别用多继承
 def __init__(self, school, name, age):self.school = schoolHuman.__init__(self, name, age)      #显式调用#为什么不传入self会报错?#类调用了实例方法,就是一个普通方法的调用,参数要传全#s1 = Student() python内部实例化机制自动帮我们调用,会补全self#对比s1.do_homewor()也不需要self,实例调用实例方法#强行需要用类调用:Student.do_homework(s1)#不建议这么干没得意义,Student.do_homework('')都可以,只要传一个参数进入就行super(Student, self).__init__(name, age)#更改父类时只需要在定义类后面的括号里修改父类名称即可
  • 子类与父类方法同名
'''def do_homework(self):print('This is a parent method')
'''def do_homework(self):super(Student, self).do_homework()  #1print('english homework')s1 = Student('人民路小学', '石敢当', 18)
s1.do_homework()    #english homework
#1 This is a parent method
#1 english homework

正则表达式与JSON

返回

  • 正则表达式是一个特殊的字符序列,检测一个字符串是否与我们所设定的字符序列相匹配,实现快速检索文本、替换文本的操作。
    ① 检查一串数字是否是电话号码
    ② 检测一个字符串是否符合E-mail
    ③ 把文本里指定的单词替换为另一个单词
import re
#几乎没有意义的常量表达式,没有体现出匹配的优势
#正则表达式的灵魂在于:规则!
a = 'C|C++|Java|C#|Python|Javascript'
r = re.findall('Python', a)      #'正则表达式'
if len(r) > 0:print('字符串中包含Python')

元字符

元字符与普通字符

import re
#找a中的所有数字
a = 'C0C++7Java8C#9Python6Javascript'
r = re.findall('\d', a)      #\d匹配一个数字符,元字符
#\D匹配所有非数字符
print(r)
#['0','7','8','9','6']

正则表达式匹配的是字符
菜鸟教程–元字符列表

字符集

import re
#找s中找出中间字符是c或者f的单词
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[cf]c', s)      #普通字符+字符集
print(r)
#[acc','afc']
r = re.findall('a[^cfd]c', s)    #取反操作
print(r)
#['abc','aec','ahc']
r = re.findall('a[c-f]c', s) #取范围
print(r)
#['acc','adc','aec','afc']
  • 普通字符用于辅助定界
  • 出现在字符集里面的字符之间是或关系

概括字符集

  • \d = [0-9]\D = [^0-9]
  • \w = [A-Za-z0-9_]匹配数字、字母、下划线,\W
    ['p','y','t','h','o','n'][' ','&','\n','\r','\t']
  • \s
    [' ','\n','\r','\t']–空白字符
  • .匹配除了换行符以外的所有符号

数量词

a = 'python 1111java678ph'
r = re.findall('[a-z]', a)
print(r)    #单个字母的序列
r = re.findall('[a-z][a-z][a-z]', a) #连续匹配3位字符
print(r)    #['pyt','hon','jav','php']
r = re.findall('[a-z]{3}', a)
print(r)    #['pyt','hon','jav','php']
r = re.findall('[a-z]{3,6}', a)  #字符位数范围3-6
print(r)    #['python','java','php']

贪婪和非贪婪

  • python默认贪婪的匹配方式,一直匹配到某个字符不满足他的要求
r = re.findall('[a-z]{3,6}?', a)  #非贪婪
print(r)    #['pyt','hon','jav','php']

匹配0次1次或者无限次

  • *匹配*前面的字符0次或者无限多次
  • +匹配*前面的字符1次或者无限多次
  • 匹配*前面的字符0次或者1次
a = 'pytho0python1pythonn2'
r = re.findall('python*', a)
print(r)
#['pytho','python','pythonn'] #n符合*匹配0次
r = re.findall('python+', a)
print(r)
#['python','pythonn']   #n符合*匹配0次
r = re.findall('python?', a)
print(r)
#['pytho','python','python']  #多出来的次数n会被去掉
  • ?可以用来去重

边界匹配

  • ^从字符串的开头开始匹配
  • $从字符串的末尾开始匹配
qq = '100000001'
r = re.findall('\d{4,8}', qq)
print(r)    #['10000000'],在表达式里面寻找,并不完整的匹配字符串
r = re.findall('^\d{4,8}$', qq)
print(r)    #[],完整匹配了字符串
r = re.findall('000', qq)
print(r)    #['000','000']
r = re.findall('^000', qq)
print(r)    #[]
r = re.findall('000$', qq)   #最后三个字符得是000
print(r)    #[]

import re
s = 'pythonpythonpythonpythonpythonpython'
r = re.findall('pythonpythonpython', s)
print(r)
#['pythonpythonpython', 'pythonpythonpython']
r = re.findall('python{3}', s)
print(r)
#[],只能匹配单个字符出现的次数
r = re.findall('(python){3}', s)
print(r)
#['python', 'python']   ????
r = re.findall('(python){3}[JS]', s)
print(r)
#[]

匹配模式参数

  • re.I表示匹配忽视字母大小写
  • re.S表示.匹配所有符号,包括\n
import re
lanuage = 'PythonC#\nJavaPHP'
r = re.findall('c#', lanuage, re.I)  #匹配忽视大小写
print(r)    #['C#']
r = re.findall('c#.{1}', lanuage, re.I)  #匹配c#和任意一个字符
print(r)    #[],.不支持\n
r = re.findall('c#.{1}', lanuage, re.I | re.S)
print(r)    #['C#\n']

re模块下的其他函数

re.sub正则替换

import re
lanuage = 'PythonC#Java'
lanuage1 = 'PythonC#JavaC#PHPC#'
r = re.findall('C#', 'GO', lanuage)
print(r)    #PythonGOJava
r = re.findall('C#', 'GO', lanuage1, 0)        #所有符号的都会被替换
print(r)    #PythonGOJavaGOPHPGO
r = re.findall('C#', 'GO', lanuage1, 1)        #符合条件的字符替换的最大次数1
print(r)    #PythonGOJavaC#PHPC#lanuage1 = lanuage1.replace('C#', 'GO')    #内置函数实现替换
print(lanuage1) #PythonGOJavaGOPHPGO
  • sub()的第二个参数可以是函数
lanuage1 = 'PythonC#JavaC#PHPC#'
def conver(value):  #传入值是C#/非字符串,返回值会替代C#passdef conver1(value):print(value)#<_sre.SRE_Match object; span=(6, 8), match='C#'>,之前偶6个字符,占用的是7和8#<_sre.SRE_Match object; span=(12, 14), match='C#'>#<_sre.SRE_Match object; span=(17, 19), match='C#'>#如何拿到c#?matched = value.group()  #表示匹配的字符串return '!!' + matched + '!!'r = r.sub('C#', convert, lanuage1)
print(r)
#PythonJavaPHP,因为返回值是空
r = r.sub('C#', convert1, lanuage1)  #c#被动态的替换
print(r)
#Python!!C#!!Java!!C#!!PHP!!C#!!
  • 把函数作为参数传入的作用
s = 'A8C3721D86'def convert(value):matched = value.group()if (int)matched >= 6:return '9'else:return '0'r = re.sub('\d', convert, s)
print(r)    #A9C0900D99

search和match

  • match()从首字母开始匹配,首字母没有就返回空
  • search()搜索字符串,一旦找到第一个就会返回
  • 两者匹配成功立刻停止搜索,findall()会匹配所有符合的结果
import re
s = 'A83C72D1D8E67'
r = re.match('\d', s)
print(r)    #None
r = re.search('\d', s)
print(r)    #<_sre.SRE_Match object; span=(0, 1), match='8'>
s = '83C72D1D8E67'
r = re.match('\d', s)
print(r)    #<_sre.SRE_Match object; span=(0, 1), match='8'>
print(r.span())
print(r.group())    #8

group分组

#匹配life和python中间的内容
s = 'life is short,i use python'
r = re.search('(life.*python)', s)
print(r.group(0))   #life is short,i use python只有一个组
r = re.search('life(.*)python', s)
print(r.group(0))   #life is short,i use python,第一组存放整体
print(r.group(1))   # is short,i use
r = re.findall('life(.*)python', s)
print(r)    #[' is short,i use ']s = 'life is short, i use python, i love python'
r = re.findall('life(.*)python(.*)python', s)
print(r.group(0))   #life is short, i use python, i love python
print(r.group(1))   # is short,i use
print(r.group(2))   #, i love
print(r.group(0,1,2))
#('life is short, i use python, i love python', ' is short,i use ', ', i love ')  用元组返回
print(r.groups())
#(' is short, i use ', ', i love ') 不会返回完整的,只会返回匹配的部分

正则表达式的学习建议

  • 完成内置函数无法完成的字符串相关问题
  • 常用的qq号,电话号码,email的匹配,可以直接用别人写好的提高效率,分析一下别人怎么写的(学习角度)
  • 避免过度依赖内置函数,有意识的多用正则表达式

JSON

  • JavaScript Object Notation–JavaScript对象标记
  • 是一种轻量级的数据交换格式
  • 字符串是JSON的表示形式
  • 符合JSON格式的字符串叫JSON字符串{"name":"qiyue"}
  • 优势:易于阅读、解析,网络传输效率高,适合用于跨语言交换数据

反序列化

  • 由字符串到某种语言上的数据结构–反序列化
json_str = '{"name":"qiyue", "age":18}'
#json格式字符串必须用双引号,因此python里外层就要用单引号
student = json.loads(json_str)
#把json字符串格式转化成python能接受的数据结构
print(type(student))    #dict
print(student)  #{'name':'qiyue', 'age':18}字典
print(student['name'])    #qiyue
print(student['age']) #18#JSON object array
json_str = '[{"name":"qiyue", "age":18}, {"name":"qiyue", "age":18}]'
student = json.loads(json_str)
print(type(student))    #list
print(student)  #[{'name':'qiyue', 'age':18}, {'name':'qiyue', 'age':18}]json_str = '[{"name":"qiyue", "age":18, "flag":false}, {"name":"qiyue", "age":18}]'
student = json.loads(json_str)
print(student)  #[{'name':'qiyue', 'age':18, 'flag':False}, {'name':'qiyue', 'age':18}]

序列化

  • python数据类型向JSON字符串转换的过程
json python
object dict
array list
string str
number int
number float
true True
false False
null None
import json
student = [{'name':'qiyue', 'age':18, 'flag':False},{'name':'qiyue', 'age':18}]
json_str = json.dumps(student)
print(type(json_str))   #str
print(json_str)
#[{"name":"qiyue", "age":18, "flag":false}, {"name":"qiyue", "age":18}]
  • 调用服务拿到字符串(JSON)进python处理

JSON/JSON对象/JSON字符串

  • JSON:是一种轻量级的数据交换格式
  • JSON字符串:符合JSON格式的字符串叫JSON字符串
  • JSON对象:JavaScript里的说法
  • JSON数据类型:中间数据类型/语言格式
  • JSON是REST服务的标准格式

Python高级语法与用法

返回

枚举

枚举是个类啊!

form enum import Enumclass VIP(Enum):#常量大写,Python没有常量概念#枚举下的类型不易更改、不能重复--枚举类型的保护功能YELLOW = 1GREEN = 2BLACK = 3RED = 4print(VIP.YELLOW)    #VIP.YELLOW,并不是1
  • 枚举的意义所在,关注的是名字而不是数字,重在标签

相比普通类有什么优势

yellow = 1
green = 2{'yellow':1, 'green':2}class TypeDiamond():yellow = 1green = 2
  • 缺陷:可变;没有防止相同值的功能

相关操作

  • 取值
#访问对应取值
print(VIP.GREEN.value)  #2
#访问标签名
print(VIP.GREEN.name)   #GREEN
print(VIP.GREEN)    #VIP.GREEN
print(type(VIP.GREEN.name)) #<class 'str'>
print(type(VIP.GREEN))  #<enum 'VIP'>
print(VIP['GREEN'])   #VIP.GREEN,通过枚举名称获得枚举类型
  • 遍历
for v in VIP:print(v)
#VIP.YELLOW
#VIP.GREEN
#VIP.BLACK
#VIP.RED
  • 比较
class VIP1(Enum):YELLOW = 1GREEN = 2BLACK = 3RED = 4result = VIP.GREEN==2
print(result)   #False
result = VIP.GREEN==VIP.GREEN
print(result)   #Trueresult = VIP.GREEN>VIP.BLACK
print(result)   #报错,枚举类型之间不支持大小比较,可以等值比较result = VIP.GREEN is VIP.GREEN
print(result)   #身份的比较,Trueresult = VIP.GREEN==VIP1.GREEN
print(result)   #False,两个不同的类,即使数值相同也不是一个枚举

枚举转换

  • 在数据库里存储–用数字代表类型
  • 编写代码时显示定义一个枚举类,用枚举类下的每一个枚举类型对应数据库中的每个数值
  • 如何把数字和枚举类型对应起来?
a = 1
print(VIP(a))   #VIP.YELLOW
#使用数值访问具体的枚举类型的一种方案

注意事项

  • 标签名不能相同,数值可以相同,但是!!
    允许有两个类型数值相等,此时第二种可以看成是第一种的别名
  • 遍历时不会打印别名
class VIP(Enum):YELLOW = 1GREEN = 1#YELLOW_ALIAS = 1BLACK = 3RED = 4print(VIP.GREEN)    #VIP.YELLOWfor v in VIP:print(v)
#VIP.YELLOW
#VIP.BLACK
#VIP.REDfor v in VIP.__members__.items():   #内置变量属性__members__的items方法print(v)
#('YELLOW', <VIP.YELLOW: 1>)
#('GREEN', <VIP.YELLOW: 1>)
#('BLACK', <VIP.BLACK: 3>)
#('RED', <VIP.RED: 4>)for v in VIP.__members__:print(v)
#VIP.YELLOW
#VIP.GREEN
#VIP.BLACK
#VIP.RED
  • IntEnum
from enum import Enum
from enum import IntEnum, unique@unique    #装饰器
class VIP(IntEnum):YELLOW = 1YELLOW_A = 1GREEN = 'str'BLACK = 3RED = 4
#报错,IntEnum的赋值必须是整型,Enum不会对枚举的数值有限制
#报错,使用装饰器后不允许相同取值
  • 枚举类型在python里面是单例模式,实例化没有意义

进阶–函数式编程

  • 基础知识用来写出代码,高阶知识用来写出可复用的代码(包、类库)
    尝试着写包和类库,体会高级语法的好处,实践出真知啊!

闭包

  • Python一切皆对象
  • 函数既可以作传入参数,又可以作返回结果
  • 闭包:函数及其在定义时外部的环境变量(非全局),不会受重新复赋值的影响
def curve_pre():a = 25          def curve(x):   return a*x*xreturn curvea = 10
f = curve_pre()
print(f(2))     #100
print(f.__closure__)    #(<cell at 0x005E4250: int object at 0x5038D5B0>,)
print(f.__closure__[0].cell_contents)   #25
  • 经典误区
def f1():a = 10def f2():a = 20     #局部变量不影响外部环境变量print(a)print(a)f2()print(a)f1()
#不是闭包
  • 小作业:计算旅行者的路径长度
#非闭包法
origin = 0def go(step):#global origin      使得该函数里面引用的origin位全局变量,不会报错new_pos = origin + step  #报错,此时局部变量origin没有值origin = new_pos #定义时在左边出现的位局部变量return new_posprint(go(2))   #2
print(go(3))    #5
print(go(6))    #11
print(origin)   #11,全局变量的值改变了#闭包方法
def factory(pos):def go(step):nonlocal pos  #指定pos为非局部变量,优先取环境变量new_pos = pos + steppos = new_posreturn new_posreturn gof = factory(origin)
print(f(3))     #3
print(f(5))     #8
print(f(7))     #15
print(origin)   #0,闭包方法调用函数不会改变全局变量
  • 闭包特点:在模块层面简介调用函数内部的局部变量

函数式编程

返回

匿名函数

lambda表达式

  • 定义时不需要定义它的函数名
lambda parameter_list: expression    #表达式def add(x, y)return x+yprint(add(1,2)) #3
f = lambda x,y: x+y
print(f(1,2))   #3
f = lambda x,y: a = x+y      #报错,冒号后面不能是代码块

三元表达式

  • xy,x大于y则返回x,否则y
#x>y ? x : y
#条件为真时返回的结果 if 条件判断 else 条件为假时的返回结果
r = x if x>y else y

map(class)

list_x = [0,1,2,3,4,5,6,7,8,9]def square(x):return x*xfor x in list_x:square(x)r = map(square, list_x)
print(r)    #<map object at 0x023D4A30>
print(type(r))  #<class 'map'>
print(list(r))  #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81],转化成列表
  • map(函数, 元素集合):将元素按函数方法映射成新的元素集合

map 与 lambda

  • 列表传入个数与lambda的参数列表个数相同
  • 结果列表元素个数取决于传入列表中元素少的那个
r = map(lambda x: x*x, list_x)
print(list(r))  #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81],可阅读性比for循环更好list_x = [0,1,2,3,4,5,6,7,8,9]
list_y = [0,1,2,3,4,5,6,7,8,9]
r = map(lambda x, y: x*x + y, list_x, list_y) #可传入可变参数
print(list(r))  #[0, 2, 6, 12, 20, 30, 42, 56, 72, 90]list_y = [0,1,2,3,4,5,6]
r = map(lambda x, y: x*x + y, list_x, list_y)
print(list(r))  #[0, 2, 6, 12, 20, 30, 42]

高阶函数

reduce

from functools import reduce#连续计算,连续调用lambda
list_x = [0,1,2,3,4,5,6,7,8,9]
r = reduce(lambda x,y: x+y, list_x)
#取前两个元素,每次lambda运算的结果作为x送入后面的运算
print(r)    #45list_x = ['0','1','2','3','4','5','6','7','8','9']
r = reduce(lambda x,y: x+y, list_x, 'aaa')
#初始值作为第一次运算的传入参数
print(r)    #aaa0123456789

filter–过滤

  • 帮助我们过滤掉不符合定义格式的元素
  • 函数返回至为False
list_x = [1,0,1,0,0,1]
r = filter(lambda x: True if x==1 else False, list_x)
print(r)    #<filter object at 0x006E4A10>
print(list(r))  #[1, 1, 1]

函数式编程vs命令式编程

  • 命令式编程:def、if else、for
  • 函数式编程:map、reduce、filter、lambda
  • lisp居然是函数式编程的鼻祖!

装饰器

  • 类此C#的特性,JAVA的注解

对修改是封闭的,对扩展是开放的

  • 非装饰器方法
import timedef f1():print('This is a function')def f2():   #没有和新增的定义关联起来,依旧是一个独立函数print('This is a function')def print_current_time(func):    #传入函数,保证函数时封闭的同时在每次调用函数前输出时间戳--新增功能print(time.time())func()print_current_time(f1)
print_current_time(f2)#和直接打印没有区别
print(time.time())
f1()
print(time.time())
f2()
  • 装饰器方法–装饰器是一种模式
import timedef decorator(func):    #装饰def wrapper():  #封装print(time.time())func()return wrapperdef f1():print('This is a function1')def f2():print('This is a function2')f = decorator(f1)
f()

python语法糖–甜、甜的?

  • 语法糖: 真正体现装饰器功能的高光时刻!即没有改变函数内部实现,也没有改变函数的调用
  • 可以接受定义时候的复杂,但是绝对不能接受调用时候的复杂!
import timedef decorator(func):    #装饰def wrapper():  #封装print(time.time())func()return wrapper@decorator   #真正体现装饰器功能的高光时刻!即没有改变函数内部实现,也没有改变函数的调用
def f1():print('This is a function1')def f2():print('This is a function2')f1()  #保持原有的调用方式不变
  • 如果函数带各种各样的参数呢?
import timedef decorator(func):    #装饰def wrapper(*args):  #封装print(time.time())func(*args)     #通用意义的变量名?return wrapper@decorator
def f1(func_name):print('This is a function named ' + func_name)@decorator
def f2(func_name1, func_name2):print('This is a function named ' + func_name1)print('This is a function named ' + func_name2)f1('lizzy')
f2('lxxx1', 'lxxx2')

如何兼容通用关键字参数?

import timedef decorator(func):    #装饰def wrapper(*args, **kw):  #封装print(time.time())func(*args, **kw)     #不管函数是怎么定义的,都可以用这个抽象的函数调用方式return wrapper@decorator
def f1(func_name):print('This is a function named ' + func_name)@decorator
def f2(func_name1, func_name2):print('This is a function named ' + func_name1)print('This is a function named ' + func_name2)@decorator
def f3(func_name1, func_name2, **kw):   #关键字参数print('This is a function named ' + func_name1)print('This is a function named ' + func_name2)print(kw)f1('lizzy')
f2('lxxx1', 'lxxx2')
f3('test1', 'test2', a=1, b=2, c='123')'''
1587521895.7875009
This is a function named lizzy
1587521895.7885008
This is a function named lxxx1
This is a function named lxxx2
1587521895.7915008
This is a function named test1
This is a function named test2
{'a': 1, 'b': 2, 'c': '123'}
'''
  • func(*args, **kw) 不管函数是怎么定义的,都可以用这个抽象的函数调用方式

装饰器小结

  • 装饰器优势
    代码的稳定性角度:对被封装的单元做出修改–通过装饰器改变函数的行为
    代码的复用性角度:语法糖

实战:原生爬虫

返回

  • 爬虫的目的性要明确

整理爬虫的常规思路

  • 鼠标右键–检查:开html信息
  • 点击信息框左上角的小箭头

    点击页面中需要的信息–自动定位到html信息中所属的代码段
  • 数据提取层级分析:精准选取定位标签,选闭合的父级别标签,尽量不要选兄弟标签
  • 正则分析
  • 数据精炼
  • 数据处理(分析完成你的需求)

错误

  • UnicodeDecodeError ‘utf-8’ codec can’t decode byte 0x8b in position 1: invalid start byte报错分析
  • StringIO和BytesIO–廖雪峰
  • gizp模块介绍–python文档

    ① 报错代码
from urllib import requestclass Spilder():url = 'https://www.douyu.com/g_jdqs'def __fetch_content(self):r = request.urlopen(Spilder.url)htmls = r.read()htmls = str(htmls, encoding='utf-8')   #报错,将htmls按utf-8编码def go(self):self.__fetch_content()s = Spilder()
s.go()

② 调试代码

from urllib import request
from io import BytesIO  #BytesIO实现在内存中读写bytes
import gzip #压缩与解压缩的模块class Spider():url = 'https://www.douyu.com/g_jdqs'def __fetch_content(self):r = request.urlopen(Spider.url)htmls = r.read()#print(type(htmls))  <class 'bytes'>buff = BytesIO(htmls)   #写入的不是str,而是经过UTF-8编码的bytes,即用一个bytes初始化BytesIO#print(type(buff))    <class '_io.BytesIO'>f = gzip.GzipFile(fileobj=buff)  #将BytesIO对象解压缩成GzipFile对象fprint(type(f))    #<class 'gzip.GzipFile'>htmls = f.read().decode('utf-8') #读取f中的字节数据并按utf-8解码为strprint(type(htmls))   #<class 'str'>a = 1def go(self):self.__fetch_content()s = Spider()
s.go()

③ 修改代码

from urllib import request
from io import BytesIO
import gzipclass Spider():url = 'https://www.douyu.com/g_jdqs'def __fetch_content(self):r = request.urlopen(Spider.url)htmls = r.read()buff = BytesIO(htmls)f = gzip.GzipFile(fileobj=buff)htmls = f.read().decode('utf-8')a = 1def go(self):self.__fetch_content()s = Spider()
s.go()
  • 我跳票了我去爬B站学习直播区了再见斗鱼!
from urllib import request
from io import BytesIO
import gzipclass Spider():url = 'https://live.bilibili.com/p/eden/area-tags?parentAreaId=1&areaId=27&visit_id=4tmkk5fiu6m'def __fetch_content(self):r = request.urlopen(Spider.url)htmls = r.read()htmls = str(htmls, encoding = 'utf-8')return htmlsdef __analysis(self, htmls):passdef go(self):htmls = self.__fetch_content()self.__analysis(htmls)s = Spider()
s.go()
  • anomalous backslash in string: ‘\s’. string constant might be missing an r prefix.
    问题:\s首先被认为是转义字符,在正则中多加一个\
    解决:([\\s\\S]*?)加一个反斜杠
  • root_info提取不到信息:页面显示的数据格式和抓取的数据格式有出入,根据抓取到的数据修改正则表达式

代码规范

  • 模块、类、方法:块注释,内部首部多行
  • 语句注释:在上面,注释上空行
  • 不要滥用空行,不要在一个函数里面写多行代码(函数越小越灵活复用性越高,10-20行,最多30行)
  • 写出来也要写好
  • 爬虫扩展:BeautifulSoup、Scrapy等框架;爬虫、反爬虫、反反爬虫;ip如果被封了–代理ip库

实现代码

  • main.py
from spider import Spiderspider1 = Spider()
spider1.go()
  • spider.py
from urllib import request
import reclass Spider():'''一个爬虫类。属性:url连接地址父集信息匹配格式root_pattern名字、人气信息的匹配格式name_pattern、number_pattern方法:外部接口go()获取页面内容__fetch_content(self)对页面内容分析提取所需信息__analysis(self, htmls)对数据提炼__refine(self, anchors)排序__sort(self, anchors)与排序规则__sort_seed(self, anchor)展示__show(self, anchors)'''__url = 'https://live.bilibili.com/p/eden/area-tags?parentAreaId=1&areaId=27&visit_id=4tmkk5fiu6m'__root_pattern = '<div class="room-anchor card-text p-relative" data-v-191d6a08>([\\s\\S]*?)</div>'__name_pattern = '<span title="([\\s\\S]*?)" data-v-191d6a08>'__number_pattern = '<span class="v-middle" data-v-191d6a08>([\\s\\S]*?)</span>'#页面显示的信息:<div data-v-191d6a08="" class="room-anchor card-text p-relative"><span data-v-191d6a08="" title="丸乌咪">丸乌咪</span><div data-v-191d6a08="" class="popular-ctnr p-absolute"><i data-v-191d6a08="" class="icon-font icon-popular v-middle dp-i-block"></i><span data-v-191d6a08="" class="v-middle">2460</span></div></div>#实际抓取的信息:<div class="room-anchor card-text p-relative" data-v-191d6a08><span title="padango" data-v-191d6a08>padango</span><div class="popular-ctnr p-absolute" data-v-191d6a08><i class="icon-font icon-popular v-middle dp-i-block" data-v-191d6a08></i><span class="v-middle" data-v-191d6a08>3199</span></div></div></div></div>def __fetch_content(self):'''获取页面的内容'''r = request.urlopen(Spider.__url)htmls = r.read()htmls = str(htmls, encoding = 'utf-8')return htmlsdef __analysis(self, htmls):'''从提取的页面内容中匹配所需信息'''root_info = re.findall(Spider.__root_pattern, htmls)anchors = []for info in root_info:name = re.findall(Spider.__name_pattern, info)number = re.findall(Spider.__number_pattern, info)anchor = {'name':name, 'number':number}anchors.append(anchor)return anchorsdef __refine(self, anchors):'''数据精炼,转化成易于处理的格式'''l = lambda anchor:{#strip()删除多余的换行和空格'name':anchor['name'][0].strip(),'number':anchor['number'][0]}return map(l, anchors)def __sort(self, anchors):'''对数据排序'''#字典不支持比较,要取可以个支持比较的元素#sorted()默认从小到大,reverse=True从大到小anchors = sorted(anchors, key=self.__sort_seed, reverse=True)return anchorsdef __sort_seed(self, anchor):'''排序规则'''r = re.findall('\\d*', anchor['number'])number = float(r[0])if '万' in anchor['number']:number *= 10000return numberdef __show(self, anchors):'''数据展示'''for rank in range(0, len(anchors)):print('rank ' + str(rank+1)+ ':' + anchors[rank]['name']+ '      ' + anchors[rank]['number'])def go(self):'''作为接口供外部调用的方法'''htmls = self.__fetch_content()anchors = self.__analysis(htmls)anchors = list(self.__refine(anchors))anchors = self.__sort(anchors)self.__show(anchors)

存在的问题与改进方向

  • 动态加载的页面只能读取30条信息–如何读取动态页面?
  • 如何使程序间隔xx时间重复爬取更新信息
  • 图形界面数据展示
  • 获得的数据还能做哪些方向的分析……?

Pythonic与Python杂记

返回

用字典代替switch

switcher = {0 : 'Sunday',1 : 'Monday',2 : 'Tuesday'
}day = 2
day_name = switcher[day]
print(day_name)day = 6
day_name = switcher[day]
print(day_name)     #报错,6不存在
#get()方法有容错性
day_name = switcher.get(day, 'Unknown')  #找不到时返回Unknown
print(day_name)
  • 字典内部对应为函数(实现一个分支多个语句)
def get_sunday():return 'Sunday'def get_monday():return 'Monday'def get_tuesday():return 'Tuesday'def get_default():return 'It\'s false.'switcher = {0 : get_sunday,1 : get_monday,2 : get_tuesday
}day = 6;
day_name = switcher.get(day, get_default)()
print(day_name)

列表推导式

a = [1,2,3,4,5,6,7,8]#map实现
b = map(lambda i: i*i, a)
print(list(b))#列表推导式实现
b = [i*i for i in a]
print(b)
#[1, 4, 9, 16, 25, 36, 49, 64]
b = [i**3 for i in a]
print(b)
#[1, 8, 27, 64, 125, 216, 343, 512]
  • 推荐:有选择性的筛选运算的场合
a = {1,2,3,4,5,6,7,8}
b = [i**2 for i in a if i>=5]
print(b)
#[25, 36, 49, 64]
b = {i**2 for i in a if i>=5}
print(b)
#{64, 25, 36, 49}
  • 列表、字典、元组、集合都可以用
  • 字典如何编写列表推导式
students = {'喜小乐': 18,'石敢当': 20,'横小五': 15
}b = [key for key,value in students.items()]
print(b)
#['喜小乐', '石敢当', '横小五']
b = {value:key for key,value in students.items()}
print(b)
#{18: '喜小乐', 20: '石敢当', 15: '横小五'}#元组不可变,操作受限
b = (key for key,value in students.items())
print(b)
#<generator object <genexpr> at 0x0059A5A0>
for x in b:print(x)
"""
喜小乐
石敢当
横小五
"""

iterator与generator

  • 可迭代对象(凡是可以被for in遍历的),迭代器
  • 可迭代对象不一定是迭代器(列表元组字典),迭代器一定是可迭代对象
  • 如何让自定义的class可以被遍历?–迭代器。
class Book:passclass BookCollection:def __init__(self):self.data = ['《往事》', '《只能》', '《回味》']self.cur = 0def __iter__(self):return self#for in调用nextdef __next__(self):if self.cur >= len(self.data):raise StopIteration()r = self.data[self.cur]self.cur += 1return rbooks = BookCollection()
#迭代器一次性
for book in books:print(book)
#迭代器异常
for book in books:print(book)print(next(books))
print(next(books))
print(next(books))
#迭代器异常
print(next(books))
  • 如何迭代两次?
books = BookCollection()
import copy
#浅拷贝
books_copy = copy.copy(books)
#迭代器一次性
for book in books:print(book)
for book in books_copy:print(book)
  • 生成器–yield的用法
def gen(max):n = 0while n<=max:#print(n),我们想要的是0-10000的返回值,而不是直接在函数内处理#接着上次执行的结果继续执行下去yield nn += 1g = gen(10000)
for i in g:print(i)

None

  • 无论是从【类型】还是【值】上面来讲,【None】都不等于【空字符串、空列表,0,False】
print(type(None))
#<class 'NoneType'>
  • not aa is None等同吗?
def fun():return None
a = fun()
if not a:print('S')
else:print('F')
#S
if a is None:print('S')
else:print('F')
#Sa = []
if not a:print('S')
else:print('F')
#S
if a is None:print('S')
else:print('F')
#F
  • 推荐的判空操作:
    if a:
    if not a:
    不要用None来进行判空操作

对象存在不一定是True

  • None永远对应False
  • 自定义的对象和True和False是怎么对应的?
class Test():passtest = Test()
if test:print('S')    #S,不存在len和bool时默认trueclass Test1():def __len__(self):return 0test = Test1()
if test:print('S')
else:print('F')   #F
  • __len____bool__内置方法
class Test():def __len__(self):return 8#只能返回int,'8'会报错,'1.0'也会报错,bool可以print(len(Test()))   #8
print(bool(Test())) #True,没有bool方法就看len方法class Test1():def __bool__(self):return False   #0报错,强制要bool类型def __len__(self):return 8print(len(Test1()))  #8
print(bool(Test1()))    #False
#加入__bool__以后bool取值不再看len

我!结!课!了!

Python语法--Mooc七月相关推荐

  1. Python 语法小知识

    为什么80%的码农都做不了架构师?>>>    序列解包       将含有多个值的序列解开,然后把值存放到变量中,当函数或者方法返回元组时这个特性很有用,可以把返回的序列值直接赋值 ...

  2. python语法书籍推荐_python语法的书

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 四大基本语法分别从变量命名规则.缩进原则.特殊关键字和特殊运算符四个方面,总结 ...

  3. python身份运算符的语法规则_7 Python语法入门之与用户交互、运算符

    本文对应的视频讲解如下: 与用户交互:python快速入门(一)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com 一 程序与用户交互 1.1.什么是与用户交互 用 ...

  4. python语法错误概述_python语法错误

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我是python中的新手,当我想在模块中编译代码时,我遇到语法错误:invail ...

  5. 人工智能实践:TensorFlow笔记学习(二)—— Python语法串讲

    Python语法串讲  大纲 2.1 Linux指令.HelloWorld 2.2 列表.元组.字典 2.3 条件语句 2.4 循环语句 2.5 turtle模块 2.6 函数.模块.包 2.7 类. ...

  6. python【数据结构与算法】Python语法查询大宝剑(全)

    最近发现自己语法基础捉急,从来没有系统学过python语法. 所以更新一份python基础语法查询大宝剑. 文章目录 1 标准库 1.1 math和cmath 1.2 string 1.3 rando ...

  7. python基本语法语句-python 语法基础篇 一

    安装篇 编辑篇: 编辑python 一 : 在终端环境下输入python命令,回车键运行.这种方式称为 交互方式. 1️⃣ 打开终端: 2️⃣ 输入python 回车 3️⃣ 输入python 语法 ...

  8. python语法手册-python语法手册

    广告关闭 腾讯云双11爆品提前享,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高满返5000元! 常用的也不超过十个,这种相对于更为复杂的html标记语言来说,markdown可谓 ...

  9. python语法教程-Python语法教程总结规范

    Python语法易错点记录 本文提供全流程,中文翻译. Chinar坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar-- 心分享.心 ...

最新文章

  1. asp.net 2.0中设定默认焦点按钮
  2. java中 private final_Java笔记:final与private关键字
  3. 总结 | “卷积”其实没那么难以理解
  4. 力扣-589. N 叉树的前序遍历
  5. CDOJ 483 Data Structure Problem DFS
  6. 数字通信原理_推荐 | 从飞鸽传书到数字信号,你不得不懂的通信原理
  7. 2种方式打开jar文件
  8. 如何拆分PDF成多个文件?这样拆分非常简单
  9. 【转载】30个高质量但免费的自学网站
  10. 基于MM、STP、ECN、MTF的外汇平台模式深度分析
  11. ie浏览器flash player不能用的解决方案
  12. 2022年企业CS1升级到CS2需要什么条件 ?有什么流程?
  13. 使用JavaFX2.0的控件
  14. 【单片机】单片机课程设计(测温打铃)附完整代码和电路图
  15. JQuery ajax使用总结
  16. GitHub 学生认证,申请 GitHub 学生包
  17. 软件产品测试验收报告介绍
  18. C#利用QQ游戏破解QQ密码
  19. 容积卡尔曼滤波CKF—目标跟踪中的应用(算法部分—I)
  20. 处理/root/jdk8/jdk1.8.0_241/bin/java: /lib/ld-linux.so.2: bad ELF interpreter: No such file or di错误

热门文章

  1. AHRS简要说明及使用例程(外加踩坑)
  2. 深度学习baseline模型_深度学习模型在序列标注任务中的应用
  3. localhost无法访问的问题
  4. jbox弹窗_强大的jquery弹出层插件jBox
  5. 文本分类模型中的“蒸”功夫
  6. UVM学习笔记--sequence和sequencer
  7. C/C++《程序设计基础(C语言)课程设计》[2023-04-20]
  8. 学堂云 减脂与运动塑形
  9. 编程语言入门YC创始人Paul Graham:如何开始创业
  10. 微信小程序:用户头像的更改与保存