Python笔记
Posted Alick陈彬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python笔记相关的知识,希望对你有一定的参考价值。
*程序:每一行程序都要执行一个运算.
*标点: 注意把输入法的"中文时使用英文标点"功能打开,因为程序中不允许有中文标点,否则会报错.
*Python解释器: 1.CPython(官方提供法的解释器,用>>>作为提示符 , 2.IPython(基于CPython之上的一个交互式解释器,用In[序号]: 作为提示符)
*编码: 第一阶段: ASCII ==> 美标, 只能有英文, 否则会乱码.
第二阶段: GBK ==> 中国人定制的GBK, 为了满足中文.
第三阶段: unicode ==> 万国码, 但有些浪费存储空间.
第四阶段: utf-8 ==> unicode的升级版, 不仅万国通用而且还省空间.
*Python的五种数据类型:1.number(数字)、2.string(字符串)、3.list(列表)、4.tuple(元组)、5.dictionary(字典)
→其实整体来说就分为两大类:数字类型(整数、浮点数、布尔、复数) 和 非数字类型(字符串、列表、元组、字典)。
→按可变类型与不可变类型分:可变类型(列表、字典)、不可变类型(数字、字符串、元组)。
*特殊字典set集合: 有一种特殊的字典 , 只有key没有value, 但由于字典的key的唯一性 , 所以set集合的元素是无序且不重复的. 可以在一个set()函数内部传入一个列表来去除重复元素.
*变量:Python中不需要声明变量,在给其赋值的同时变量就被创建了,变量名只能包含字母、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头。
*变量作用域:局部作用域(local)、闭包函数外的函数中(enclosing)、全局作用域(global)、内建作用域(built-in)。
那么: global可以用来声明全局变量从而在内部函数改变全局变量的值; nolocal的作用与global类似, 不过nolocal是用来声明相对外层函数的变量而不是最外层的全局变量.
*常量: 所谓常量就是不能变的变量,用赋值语句定义 , 所有字母都要大写 , 单词与单词用下划线分隔.
*布尔变量类型:True为真(1),Fause为假(0)。
*BIF:内置函数,如print、int、input......
*编译型语言与解释型语言的区别:1.编译型语言是统一编译,一次性执行,如C、C++类型语言;
2.解释型语言是编译一行,执行一行。
*字符串:就是一系列字符。在Python中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号。
*关键字、函数、方法:1.关键字: import、def、del、True ... ,关键字是内置的,具有特殊意义的标识符,不需要加小括号。
2.函数: input()、print() ... ,函数封装了独立的功能,可以直接调用,需要死记硬背,需要加小括号。
3.方法:.title() 、 .upper() 、 .remove() ... ,方法与函数类似,也封装了独立的功能,需要通过对象来调用,表示针对这个对象要做的操作,不需要死记硬背,需要加小括号。
==>小技巧:可用dir()函数查看一个对象具有的所有方法,所以方法是不需要死记硬背的。
$注意: 一个函数或者方法只要给了形参,那么在调用时就一定要传递相应的实参;如果不想传入实参,又想定义属性,可以在函数或方法的内部进行定义.
$函数与方法的关系: 用def关键字定义封装了一定功能的代码块就是一个函数func() , 当这个函数被对象(对象可以是一个实例, 可以是一个类, 也可以是一个模块)"对象.func()"的方式调用时 , 这个func()又可以被称之为方法.
*函数的参数类型: 1.必须参数: 调用函数时必须要传入的参数, 传入参数时要按照顺序传入.
2.默认参数: 参数可以有默认值,当一个参数有默认值时,调用时如果不传递此参数,会使用默认值, 如果传递则覆盖掉默认参数(默认参数要放在"必须参数"后面, "不定长参数"前面)
3.不定长参数: *args **kwargs => *args接收"无名不定长参数", 放到一个元组里面; **kwargs接收"有名不定长参数", 放到一个字典里面.
# 注意: 一个函数有混合参数时, 参数的传入顺序为 (必须参数, 默认参数, *args, **kwargs)
例: def person(name, age=18, "hello", "world", job="doctor", height=178, weight=65)
*加不加引号: Python中, 形参不加引号, 实参要加引号; 本质是变量不加引号, 字符串要加引号, 所以判断一个参数加不加引号, 就看它是一个形参变量, 还是一个实参字符串.
*高阶函数: 1. 函数名可以作为参数传入 2. 函数名可以作为返回值.
*str()函数:将括号内数据转换成字符串类型.
*int()函数:将括号内数据转换成整数类型.
*if语句:and为同时满足,or为满足一个就行; in为包含在内,not in为不包含在内。
if语句小结:总之,如果你只想执行一个代码块,就使用if-elif-else 结构;如果要运行多个代码块,就使用一系列独立的if 语句。
*列表_常用"方法"和"函数": .insert(2,"new") # 增,在列表第三个位置插入元素new。
.append("new") # 增,在列表末尾追加元素new。
.extend(list2) # 增,在列表1末尾追加列表2。
.remove("old") # 删,移除列表中指定元素"old"。
.pop(2) # 删,弹出(删除)列表第三个元素。
del list[2] # 删,从内存中删除列表中第三个元素。(注:删除后不再可以使用这个元素)
.clear() # 删,将列表清空。
list[2]="new" # 改,修改列表第三个元素为new。
.index("demo") # 查, 查询demo这个元素的索引
.sort() # 序,升序。
sorted() # 序, 临时升序.
.sort(reverse=True) # 序,降序。
.reverse() # 序,逆序。
len(list) # 计,计算列表长度,即列表内元素个数。
.count() # 计,统计列表中某一个元素出现的次数。
print(list[0:3]) # 输出列表第一个到第三个元素。
*特殊算术运算符: // # a/b取整
% # a/b取余
*成员运算符: in # 包含在一个数据类型里面。
not in # 不包含在一个数据类型里面。
*For循环: for循环就是对一个列表做迭代遍历,将列表中的每个元素依次拿出来做相同的操作。
*break:打破当前循环,既不执行剩下循环也不执行else部分。
*continue:程序执行到continue处时,不在执行后面的部分,直接跳转到循环开始位置继续执行。
*input()函数:input函数输出的都是字符串类型。
*格式化操作符:%s(代表非数字类型)、%d(代表整数,%05d表示5位数计数法)、%f(代表小数,%.2f表示保留2位小数)
注:1.%d%%表示百分之多少。 2.一行内容有多个变量需要用到格式化操作符时是%(price,weight,money)。
*标识符:给变量或函数起的名字就是标识符。
*逻辑运算符:与(and)、或(or)、非(not),注意"非"是对某一个条件进行取反操作。
*随机数:1.import random(先导入一个随机数工具包) 2.a=random.randint(0,100) (再将0~100的随机整数赋值给一个变量)。
*字符串中的转义字符:\\(反斜线)、\"(双引号)、\‘(单引号)、\n(换行)、\t(制表符,使多行输出内容对齐)。
*列表、元组、字典取值共同点:三者取值都是在其标识符后面接中括号[ ].
*列表里面包含列表: 例 L = [ ["Apple","Google"] , ["Mark","Lisa"] ] 那么: L[0][1] 代表第一个列表的第二个元素.
*range()函数: range(5)代表序列0-4 , 默认生成从0开始小于5的整数 , 如果要指定起始数,格式是 range(1,5)则会生成1-4的序列 , 但range函数生成的只是序列而已,可以用list(range(1,5))来生成一个列表.
*字典: 用大括号{ }建立的多组无序的键值对。 dict={"name:"小明","age":18,"height":1.75}
dict["name"]="小红" # 修改字典元素
dict["weight"]=65 # 增加字典元素(没有这个元素的话, 就是增加此元素, 有这个元素的话, 就是修改元素)
dict.pop("name") # 删除字典元素
dict.update(dict2) # 将字典dict与字典dict2合并
dict.keys() # 返回包含字典所有keys的列表
dict.values() # 返回包含字典所有values的列表
dict.get() # 获取指定键的值, 若没有这个键则返回None.
dict.clear() # 清空字典
len(dict) # 统计字典的元素个数.
→小结:增加字典元素方法与修改元素是一样的,如果原本有这个元素就是修改,原本没有就是增加;定义字典时最好一组键值对独立占用一行,这样看起来更直观。
*字符串: .capitalize(): 整体首字母大写 .isspace():判断字符串中是否仅包含字符 .strip():去掉字符串前后的空白字符
.title(): 每个单词首字母大写 .isdecimal():判断字符串中是否仅包含阿拉伯数字 .center():将字符串文本居中
.upper(): 所有字母都大写 .isalpha():判断字符串中是否仅包含字母 .split():将字符串拆分成一个列表
.lower(): 所有字母都小写 .startswith():判断字符串是否以指定字符串开始 .join():将一个列表拼接成一个字符串(在进程章节里面, pro.join()是指等子进程结束后父进程才结束)
.swapcase(): 大小写反转 .endswath():判断字符串是否以指定字符串结束
...
*字符串的切片: num_str = "0123456789"
num_str[0:3] = "012" num_str[0:7:1] = "0123456"
num_str[0: ] = "0123456789" num_str[0:7:2] = "0246"
num_str[ :3] = "012" num_str[0:7:3] = "036"
num_str[ : ] = "0123456789" num_str[ : :-1] = "9876543210" # 字符串的逆序
num_str[ :-1] = "012345678"
切片公式 ==> 拿第m到第n个元素: demo[m-1 : n]
*公共方法: 1.内置函数:len() 、 del() 、 max() 、 min() 注:max()和min()比较对象是字典时,比较的是key。
2.切片:字符串、列表、元组的切片方法相同。不适用于无序数据类型"字典"。
3.运算符:+ 、 * 、 in 、 not in
*模块、包、库: 1.模块:包含并且有组织的代码片段。
2.包:是一个有层次的文件目录结构,它定义了由n个模块或n个子包组成的Python应用程序执行环境。
3.库:具有相关功能模块的集合。这也是Python的一大特色之一,即具有强大的标准库、第三方库以及自定义模块。
*爬虫:Python爬虫架构主要由五个部分组成,分别是调度器、URL管理器、网页下载器、网页解析器、应用程序(爬取的有价值数据)。
(https://blog.csdn.net/sinat_29957455/article/details/70846427)
全局变量和局部变量:在函数内部定义的变量叫局部变量,在函数外部定义的变量叫全局变量。要想在函数内部修改全局变量需要使用关键字global声明一下(global num).
小技巧:要想同时修改出现在程序中多个位置的某一个变量的名称,可以选中该变量右键→refactor→rename来统一修改。
*return:如果在定义函数时后面需要用到该函数的返回值,就需要在定义函数末尾用到关键字return来将值传递给函数。格式:return result,若要返回多个值,则是:return result1,result2
注意:程序执行到return处时,会直接把结果传递给函数,不会再执行return后面的部分.
* += : 此赋值运算符对列表不是先相加再赋值操作,而是对列表调用.extend()方法。
面向对象
*面向对象核心:类和对象。 根据图纸制造出很多飞机,其中图纸就是类,飞机就是对象。
简单来讲,类就相当于制造飞机的图纸,是一个模板,是负责创造对象的。
*类的三要素:类名、属性、方法。
类名:这类事物统称的名字,满足大驼峰命名法(即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。)。
属性:这类事物具有的特征,通常是“名词”。
方法:这类事物具有的行为,通常是“动词”。
*类创建的对象:由同一个类创建的不同的对象之间的属性是互不干扰的.
*类常用的内置方法: 1. __init__ : 初始化方法(定义类的属性),注意: 在定义初始化属性时,需要外界传递的属性就给其定义形参,不需要外界传递时可以不用定义形参,在该方法内部自己定义就可以了.
2. __str__ : 此内置方法可以定制对象变量的输出信息,此方法必须要用return返回一个字符串.
3. __del__: 删除调用对象保存的内存地址.
*__方法名(): 方法名前面加两个下划线代表类的私有方法 , 只允许在类内部调用
*多个类: 当一个类a的属性是另一个类b创建的对象x时,不需要再在类a中再次定义该属性了,直接调用类b给该对象x定义的属性就可以了.
注意: 只有当这个对象x在类a中的某个方法中通过self.声明了,类a的其它的方法才能使用这个对象x.
*None: 在定义属性时,如果不知道设置什么初始值,可以设置为None.
*is 与 == 的区别: is 是用来判断两个变量引用对象是否为同一个,即内存地址是否一样.
== 是用来判断引用对象的值是否相等.(==只用在条件判断语句的if后面)
*私有属性和私有方法: 如果通过一个类创建的对象,不想被外界访问到的属性或者方法,只需要在属性名或方法名前加两个下划线. 例如: self.__name=name def __fire()
继承
*单继承: 子类拥有与父类同样的属性和方法,就可以直接继承父类的属性和方法. 如: 父类class Animal , 子类class Dog(Animal) ,子类class Xiaotianquan(Dog)
*多继承: 子类拥有多个父类叫做多继承 , class 子类(父类1 , 父类2 ...)
*多态: 不同的子类继承自同一个父类 , 但这两个子类又有不同的特性 , 就称为多态.
*子类方法的重写: 若父类中的方法无法满足子类的需求,则可以在子类中对需要修改的方法进行重写,方法名与父类中的一样.
*子类对父类方法的扩展: 即父类封装的方法实现是子类方法的一部分,就可以使用扩展的方式, 还是先def eat(): super().eat()
*基类和派生类: 基类即父类 , 派生类即子类.
*类属性和类方法: 类从宏观上其实也可以看成一个对象,所以也可以设置类属性和类方法.
类属性:直接在类名下方使用赋值语句就可以定义"类属性",外部可以通过 类名. 的方式来访问类属性.
类方法:在定义方法上方加@classmethod,且方法第一个参数是cls.
*实例方法、类方法、静态方法: 1.实例方法: 即对象方法 通过 实例名. 的方式来调用.
2.类方法: @classmethod 通过 类名. 的方式来调用.
3.静态方法: @staticmethod ,不需要访问实例属性和类属性的方法就设置为静态方法,不需要设置第一个参数. 通过 类名. 的方式来调用.
*捕获异常: try:
可能会出现异常的代码
except 错误类型1:
相应的处理
except 错误类型2:
相应的处理
except Exception as result:
print("未知错误:%s"%result)
else:
没有异常会执行的部分
finally:
无论是否出现异常都会执行的部分
*抛出异常: 用Exception类创建一个异常对象exp, 然后用raise关键字将异常抛出,让主程序部分接收这个异常,并对异常做出处理.
exp = Exception("密码长度不够")
raise exp
try:
主程序部分
except Exception as result:
未知错误,,,,,
*模块: 导入模块的方法 1.import 模块名 # 导入整个模块,此方法需要通过 模块名. 的方式来调用内部工具.
2.import 模块名 as 别名 # 导入整个模块并给其起一个别名,用大驼峰命名法.
3.from 模块名 import 函数/类/全局变量 # 从一个模块中导入一个工具(函数/类/全局变量), 用这个方式导入是为了后面调用时方便.
4.from 模块名 import * (不推荐) # 从一个模块中导入所有工具.
注意: 在开发时,给文件起名不要和系统的模块文件重名,因为python的解释器在导入模块时,会先搜索当前目录,找不到再搜索python的系统目录.
*包: 由一个名为__init__的模块和其它多个模块组成的. (__init__模块用于指定包中哪些模块可以被导入使用)
*__name__: __name__是内置属性,每一个模块的__name__属性都是"__main__", 当该模块被导入到其它程序时,__name__属性就变成模块名,因此:
注意: 在开发完一个模块时.如果想要对模块内的工具功能(函数/类/全局变量)做一个测试,则可以在内置属性__name__的判断语句下方来执行
只有这样做,该模块被导入到其它程序时,测试部分才不会在其它程序内执行.
语法格式: if __name__ == "__main__":
测试1
测试2
*文本文件和二进制文件: 可以用文本编辑软件查看的就是文本文件 , 而二进制文件不是给人直接阅读的,而是提供给其它软件使用的.
*文件操作三部曲: 打开 → 读写 → 关闭 , python中对应的是一个函数三个方法 , 即open() read() write() close()
file_01 = open("文件名","r") , 以只读方式打开 , ==> text = file_01.read()
file_01 = open("文件名","w") , 以只写方式打开 , ==> file_01.write("要写入的内容")
file_01 = open("文件名","a") , 以追加方式打开 , ==> file_01.write("要写入的内容")
注意别忘了关闭文件 , ==> file_01.close()
*文件读写升级版: str_test1 = "先创建txt文件再写入内容: 我是大帅哥"
# with open("file_path.xxx", "w") as f 语句会先创建一个xxx格式的文件并以只写方式打开 ,
# 再往文件里面写入内容(以只写方式会覆盖原内容), 而且这种语句的好处是不用再在末尾调用.close()关闭文件.
# 常用的方式有: "r", "w", "a", "rw", "rb", "wb", "ab" ==>(b是指以二进制读写文件, 最后操作的话要解码).
with open("./file.txt","w") as f:
f.write(str_test1)
str_test2 = ", 我是大美女!"
with open("./file.txt","a") as f: # "a"是以追加的方式打开文件
f.write(str_test2)
with open("./file.txt","r") as f: # "r"是以只读方式打开文件
print(f.read())
*read(),readline(),readlines()的区别: 1.read(): 读取整个文件到一个字符串
2.readline(): 逐行读取到一个字符串 , 每次只读取一行.
3.readlines(): 逐行读取整个文件到一个列表.(推荐做法)
*pip : pip是一个现代的 , 通用的Python包管理工具。提供了对Python包的查找、下载、安装、卸载的功能。(需要先在网上下载pip工具)
官方提供的pip示例 :
pip install requests
pip search xml
pip show beautifulsoup4
pip uninstall requests
Pygame:
*四部曲: import pygame # 导入pygame模块
pygame.init() # 初始化
代码部分 # 主程序部分
pygame.quit() # 退出,释放内存
*元素: 在游戏中,所有的可见元素都是以矩形区域来描述位置的.
*pygame.Rect(): pygame模块中的Rect类 , 创建一个对象hero(x,y,width,height) ,其中四个属性分别代表矩形坐标,宽度,高度.
*pygame.display(): display模块用于创建游戏窗口. 调用.set_mode(width,height)方法来初始化显示游戏窗口.
*游戏的两个组成部分: 1.游戏初始化(设置游戏窗口 , 绘制图像的位置 , 设置游戏时钟)
2.游戏循环(设置刷新帧率 , 检测用户交互 , 更新所有的图像位置 , 更新屏幕显示)
*游戏的两个组成部分升级版: 1.游戏初始化(设置游戏窗口 , 创建游戏时钟 , 创建精灵和精灵组)
2.游戏循环(设置刷新帧率 , 事件监听 , 碰撞检测 , 更新/绘制精灵组 , 更新屏幕显示)
*while True: 强制无限循环.
*模块导入顺序: 在使用import关键字导入模块时 , 建议的导入顺序是: 1.标准模块 2.第三方模块 3.自定义的模块
*pass: pass语句什么都不做,实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass ,让代码能运行起来。
*列表生成式: print([x*x for x in num_list])
print([x*x for x in num_list if x%2 == 0])
print([a+b for a in list1 for b in list2])
*生成器: 通过列表生成式,我们可以直接创建一个列表 ,但是,受到内存限制,列表容量肯定是有限的. 在Python中,有种一边循环一边计算的机制,列表元素可以按照某种算法推算出来,
称为生成器:generator. 生成器只是把列表生成式的 [] 改成 () ,然后用for循环来遍历它.
*网站和域名的区别:
让我们来解析一下下面这一段:
http://mail.163.com/index.html
1.http://:这个是协议,也就是HTTP超文本传输协议,也就是网页在网上传输的协议.
2.mail:这个是服务器名,代表着是一个邮箱服务器,所以是mail.
3.163.com:这个是域名,是用来定位网站的独一无二的名字.
4.mail.163.com:这个是网站名,由服务器名+域名组成.
5./:这个是根目录,也就是说,通过网站名找到服务器,然后在服务器存放网页的根目录.
6.www.baidu.com www是服务器名 , baidu.com是域名.
进阶
*正则表达式: 是用于快速从一大堆字符中快速找出想要的子字符串的一种表达方式 , 函数+表达方式=快速找出子字符串。
(主要应用在爬虫) 在正则表达式中,如果直接给出字符,就是精确匹配。用\d可以匹配一个数字,\w可以匹配一个字母或数字,所以:
‘00\d‘可以匹配‘007‘,但无法匹配‘00A‘;
‘\d\d\d‘可以匹配‘010‘;
‘\w\w\d‘可以匹配‘py3‘;
.可以匹配任意字符,所以: ‘py.‘可以匹配‘pyc‘、‘pyo‘、‘py!‘等等。
要匹配变长的字符,在正则表达式中,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符.
贪婪匹配: 正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。
1.正则表达式re.match()函数: 原型==> match(正则表达式, 要匹配的字符串, flags=0)
功能: 从字符串的起始位置匹配一个模式, 如果没有匹配到就返回None.
2.正则表达式re.search()函数: 原型==> search(正则表达式, 要匹配的字符串, flags=0)
功能: 扫描整个字符串, 并返回第一个成功的匹配.
3.正则表达式re.findall()函数: 原型==> findall(正则表达式, 要匹配的字符串, flags=0)
功能: 扫描整个字符串, 并返回整个结果列表.
flags: 标志位, 用于控制正则表达式的匹配方式, 有以下6个值:
re.I: 忽略大小写
re.L: 做本地化识别(基本用不上)
re.M: 多行匹配, 影响^和$
re.S: 使.匹配包括换行符在内的所有字符
re.U: 根据Unicode字符集解析字符, 影响\w \W \b \B
re.X: 使我们以更灵活的格式理解正则表达式(也不常用)
^: 匹配是不是以某某开头的, 如果不是则返回None
$: 匹配是不是以某某结尾的, 如果不是则返回None
[34578]: 取34578中的任意一个.
==> 分组: 除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。比如:
>>>str = re.match(r‘^(\d{3})-(\d{3,8})$‘, ‘010-12345‘)
>>>str
<_sre.SRE_Match object; span=(0, 9), match=‘010-12345‘>
>>> str.group(0)
‘010-12345‘
>>> str.group(1)
‘010‘
>>> str.group(2)
‘12345‘
>>> str.groups()
(‘010-12345‘, ‘010‘, ‘12345‘)
==> 编译: 如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配.
>>>re_telephone = re.compile(r‘^(\d{3})-(\d{3,8})$‘)
>>> re_telephone.match(‘010-12345‘).group(1)
‘010‘
>>> re_telephone.match(‘027-12345‘).group(1)
‘027‘
*JSON/XML: JSON: (JavaScript Object Notation ) 是一种轻量级的"数据交换格式", 类似键值对格式.
Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数:
json.dumps(): 对数据进行编码(python=>json).
json.loads(): 对数据进行解码(json=>python).
json.dump(): 对文件进行编码.
json.load(): 对文件进行解码.
XML: (eXtensible Markup Language)标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言, 现在基本不用XML了。
小结: JSON和XML说白了就是将数据编码成一种特殊格式 , 也可以解码为原来的格式, JSON现在的市场份额占95%, XML占5%.
*CGI: CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口。
*IO同步和异步: cpu等一个进程执行完再去执行下一个进程叫IO同步(单进程) , cpu不用等一个进程执行完就去执行其它的进程就叫异步IO(多进程).
*多进程/多线程: Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,
因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
如果你打算编写多进程的服务程序,Unix/Linux无疑是正确的选择。虽然Windows没有fork调用 , 由于Python是跨平台的,
自然也应该提供一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。
小结: 考虑到CPU和IO之间巨大的速度差异,一个任务在执行的过程中大部分时间都在等待IO操作,单进程单线程模型会导致别的任务无法并行执行,
因此,我们才需要多进程模型或者多线程模型来支持多任务并发执行。
(一个cpu有多个核,可以同时有多个进程 , 一个进程可以有多个线程)
*TCP/UDP: 1. TCP是可靠连接 , 大多数连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。
2. UDP是不可靠连接 , UDP是面向无连接的协议 , 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,能不能到达就不知道了。
虽然用UDP传输数据不可靠,但它的优点是和TCP比,速度快,对于不要求可靠到达的数据,就可以使用UDP协议。
*SMTP/POP3: 1.SMTP:SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件 ,
Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。
2.POP3:收取邮件最常用的协议是POP协议,目前版本号是3,俗称POP3。
收取邮件分两步:
第一步:用poplib把邮件的原始文本下载到本地;
第二部:用email解析原始文本,还原为邮件对象。
*Web框架: Flask...
*Webapp: web应用程序
*应用程序的两种模式: C/S: client/server , 即 客户端/服务器端 程序.
B/S: browser/server , 即 浏览器端/服务器端 程序.
*Webapp与网站的区别: webapp是功能性的 , 而网站只是展示性的.
*静态网页和动态网页的区别: 静态网页想要更新内容必须手动更新html文档再上传到服务器 , 而动态网页会根据用户的要求和选择动态改变和响应 , 无须手动更新html文档便会自动生成新的页面.
*time模块: 1.time.time() 返回当前时间的时间戳(1970纪元后经过的浮点秒数).
2.time.localtime() 返回本地时间 , 但可读性不高.
3.time.asctime() 将2的值作为参数传入 , 返回一个可读性高的时间格式.
4.time.sleep(secs) 函数推迟调用线程的运行 , 可通过参数secs指秒数,表示进程挂起的时间.
*装饰器: python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,
使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
*闭包: 闭包就是装饰器的原理, 装饰器只是给最外层函数起的名称.
*前端: HTML定义了页面的内容,CSS来控制页面元素的样式,而JavaScript负责页面的交互逻辑。
*Webapp实质: 一个Web应用的本质就是:
浏览器发送一个HTTP请求;
服务器收到请求,动态生成一个HTML文档;
服务器把HTML文档作为HTTP响应的Body发送给浏览器;
浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
*url: 统一资源定位符 , 互联网上每个资源都有一个唯一的地址 , 即url , 可以简单理解为资源的链接.
*MVC: Model-View-Controller,中文名“模型-视图-控制器”.
*API: 简单来说就是函数。比如你写了一个库,里面有很多函数,如果别人要使用你这个库,但是并不知道每个函数内部是怎么实现的。
使用的人需要看你的文档或者注释才知道这个函数的入口参数和返回值或者这个函数是用来做什么的。对于用户来说 ,你的这些函数就是API。
API(Application Programming Interface应用程序编程接口) 是一些预先定义好的函数,目的是提供应用程序以及开发人员基于某软件或硬件得以访问一组例程的能力。
*服务器: 不同类型(功能)的服务器只是server system上装的软件不一样而已 , 比如web服务器 , 文件服务器 , 邮件服务器 , 数据库服务器 , 各种不同功能角色的服务器就是装的各自
对应的软件而已.
*关系型数据库: 关系型数据库是由多张能互相联接的二维行列表格组成的数据库。
*NoSQL: NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,是一项全新的数据库革命性运动 , 泛指非关系型的数据库。
随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,
暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,
尤其是大数据应用难题。
==>MySQL数据库操作(工作中用的最多的其实是数据的查询操作)
*在终端中开启数据库: 方式1.在管理员身份运行cmd终端中开启数据库: net start mysql57(服务名称) ==>连接数据库: mysql -u 用户名 -p ==> 输入密码
方式2.在mysql-client里面开启数据库: 直接输入密码就可以进入了.
*退出登录: exit
*远程连接数据库: mysql -h ip地址 -u 对方用户名 -p ==> 输入对方密码
*数据库类型: 关系型数据库: MySQL, Oracle等; 非关系型数据库(NoSQL): MongoDB, Redis等.
*数据库操作: show databases; 查看所有数据库 # 查看数据库,detabase要加复数s
create database demo charset=utf8; 创建数据库demo # 数据库命令末尾要加分号;
drop database demo; 删除数据库demo
use demo 切换数据库 # 要操作数据库得先选择使用一个数据库
select database; 查看当前使用的数据库
select version(); 查看MySQL的版本
*表操作: show tables; 查看所有的表 # 查看表也要加s
create table demo(列1,列2,...); 创建表demo 例: create table demo(id int auto_increment primary_key, name varchar(20))
drop table demo; 删除表demo
desc demo; 查看表结构
show create table demo; 查看创建表demo所使用的语句
rename table demo to newdemo; 将表demo的表名修改为newdemo
*数据操作: 增: insert into 表名 values(...); 全列插入
insert into 表名 values(...),(...),...; 全列插入多条数据
insert into 表名(列1,列2,...) values(值1,值2,...) 缺省插入
删除: delete from 表名 where 条件; 删除表内数据(警告:后面不加where条件会将表内数据全部删除) # 例:delete from student where id=4;
改: update 表名 set 列1=值1,列2=值2,...where 条件; 修改表内数据(警告:后面不加条件会将全部列都修改) # 例:update student set name=tom,age=18 where id=7;
查: select * from 表名; 查看某一个表里面的所有数据(这里的*代表所有的列, 如果只想查询部分列可用逗号分隔, 例select name,age from 表名;)
条件查询: a.语法: select * from 表名 where 条件;
b.比较运算符(=, >, <, >=, <=, !=): 例: select * from student where id>=3;
c.逻辑运算符(and, or, not): 例: select * from student where id>=3 and gender=0; 查询id>=3且性别为女的学生
d.模糊查询: like: %表示任意多个任意字符、 _表示一个任意字符
例: select * from student where name like "周%"; => 得到结果如周杰伦, 周星驰...
select * from student where name like "周_"; => 得到结果如周迅...
e.范围查询: 例: select * from student where id in (2,7,12); # 查询id为2,7,12的学生
select * from student where id between 5 and 10; # 查询id在5-10之间的学生
f.空查询: 例: select * from student where address is null; # 查询住址为空的学生(非空是not null)
g.优先级: 小括号 > not > 比较运算符 > 逻辑运算符 ; and > or =>可用()来改变优先级
h.排序: select * from 表名 order by 列1 asc/desc, 列2 asc/desc, ... ; # asc升序 desc降序
==>SQLAlchemy操作
*用SQLAlchemy初始化数据库连接: 数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名
*SQLAlchemy介绍: SQLAlchemy是Python编程语言下的一款开源软件 , 提供了SQL工具包及对象关系映射(ORM)工具 ,
SQLAlchemy首次发行于2006年2月,并迅速地在Python社区中最广泛使用的ORM工具之一,不亚于Django的ORM框架。
常用的SQLalchemy字段类型:
类型名 python中类型 说明
Integer int 普通整数 , 一般是32位.
String str 变长字符串
Float float 浮点数
常用的SQLalchemy列选项:
选项名 说明
primary_key 如果为True , 代表表的主键
unique 唯一的 , 代表这列不允许出现重复的值
*SQLALchemy数据增删改: db.session.add(user1) # 添加元素到数据库的session中
db.session.add_all([user1,user2]) # 添加多个元素(以列表形式)到session中
db.session.delete(user1) # 删除数据库实例对象
db.session.commit() # 提交数据库的修改(包括 增/删/改)
db.session.rollback() # 数据库的回滚操作
*SQLALchemy数据查询: 1.常见的SQLALchemy查询执行器
方法 说明
all() 以列表形式返回查询的所有结果
first() 返回查询的第一个结果 , 如果未查到 , 返回None
get() 返回指定主键对应的行 , 如果不存在 , 返回None
count() 返回查询结果的数量
2.常见的SQLALchemy查询过滤器
过滤器 说明
filter() 把过滤器添加到原查询上 , 返回一个新查询 # 模型(类).属性 ==
filter的功能更强大 , 可以实现更多的一些查询 , 支持比较运算符
filter_by() 把等值过滤器添加到原查询上 , 返回一个新查询 # 属性 =
示范: 查询所有用户数据 User.query.all()
查询用户数量 User.query.count()
查询第一个用户 User.query.first()
查询id为4的用户(3种方式) User.query.get(4)
User.query.filter_by(id=4).first() # .first()前面是查询, .first()才是拿到这个数据.
User.query.filter(User.id == 4).first()
*ipython:
In [11]: role1.users_role In [13]: user1.role In [14]: user3.role In [15]: user2.role.name
Out[11]: [Role:1 Tom] Out[13]: Role:1 admin Out[14]: Role:2 user Out[15]: ‘user‘
*get和post方法区别: 1.get的方式是把数据在地址栏中明文的形式发送, post则不是,而且post可以传递的数据比get多;
2.get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;
3.在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式.
*route装饰器: 我们使用 route() 装饰器告诉 Flask 什么样的URL 能触发我们的函数。
*视图函数: 用return来返回我们想要显示在用户浏览器中的信息。
*路由变量: 用尖括号来表示路由变量@app.route(‘/user/<username>‘)
*session和cookie的区别: session保存在服务器端, cookie保存在客户端. (比如浏览器登录账号名密码的时候, 选择记住密码就是由cookie保存在用户硬盘里的)
*encode和decode: str = "中文"
str1 = str.decode("utf-8") # 将utf-8码解码成unicode
str2 = str1.encode(‘utf-8‘) # 又将unicode码编码成utf-8
进程与线程:
*进程: 进程是系统中程序执行和资源分配的基本单元, 每个进程都有自己的数据段(存储数据)、代码段(存储代码)、堆栈段(对象和变量). # 全局变量等资源在多个进程中不能共享, 在子进程中修改全局变量对父进程中的全局变量没有影响.
*线程: 在一个进程内要同时干多件事, 就得同时运行多个"子任务", 这些子任务称为线程; 每个线程共享这个进程的所有资源(变量和数据等)和内存空间, 所以在子线程里面可以修改该进程的变量.
*多任务: 操作系统可以同时运行多个任务, 每个任务就是一个进程或者一个线程.
*并发: 并发是指一个处理器同时处理多个任务; 由于cpu调度执行的速度太快了, 所以看起来是同时执行, 实际上是轮流交替执行的.
*并行: 并行是指多个处理器同时处理多个任务.
*单核cpu实现多任务的原理: 操作系统轮流让各个任务交替执行, 由于cpu调度执行的速度太快了, 导致我们感觉就像所有的任务都在同时执行一样.
*多核cpu实现多任务的原理: 由于实际任务数量是远远多于cpu的核心数量的, 所以操作系统会自动把很多任务轮流调度到每个核心上执行.
*实现多任务的方式: 1. 多进程模式(用的较多): 一个父进程, n个子进程, 进程由操作系统来调度执行没有顺序; 要想让所有子进程结束后再让父进程结束, 可在子进程末尾使用 .join()方法.
2. 多线程模式(用的最多): 一个父线程, n个子线程, 线程由操作系统来调度执行没有顺序, 要想线程顺序执行, 需要加锁(Lock); 要想所有子线程结束后再让父线程结束, 可在子线程末尾使用 .join()方法.
3. 协程模式(用的很少): 协程看上去也是子程序, 但执行过程中, 在子程序的内部可中断, 然后转而执行别的子程序, 不是函数调用.
4. 多进程+多线程(一般不建议使用)
*多进程模块: multiprocessing, 它里面的Process类是用来创建一个进程实例的, Pool线程池类是用来创建多个进程实例的.
*线程模块: threading, 它里面的Thread类是用来创建一个线程实例的, Lock类是用来创建一个锁实例的.
*计算机IO操作: IO指的是计算机执行读写操作, 由于计算机执行读写操作的速度比cpu和内存的速度慢的多得多, 所以C语言这种底层计算机语言虽然cpu的速度比python快很多, 但是有时候还是得等待计算机执行IO操作, 所以python在某些领域才有竞争力.
以上是关于Python笔记的主要内容,如果未能解决你的问题,请参考以下文章