初级阶段

1.基本使用

  1. 输入输出

    • print()打印到屏幕

    • 输入函数:输入的数会是字符串格式,口号中双引号引起来可以添加提示信息。

      • input()

      • raw_input()

  2. 进入和退出python命令窗口中

    1. 进入:python

    2. 退出函数:exit()

  3. 执行python文件

    1. 想要执行命令的话想要找到文件然后用(python)文件和后缀名

    2. 如:a.py

  4. 同一行显示多条语句

    1. Python可以在同一行中使用多条语句,语句之间使用分号(;)分割,以下是一个简单的实例。

    2. import sys; x = ‘runoob’; sys.stdout.write(x + ‘\n’)

  5. 帮助信息

    1. 很多程序可以执行一些操作来查看一些基本信息,Python可以使用-h参数查看各参数帮助信息:

      1. $ python -h

      2. 我们在使用脚本形式执行 Python 时,可以接收命令行输入的参数,具体使用可以参照 Python 3 命令行参数。

      3. python的第一行命令 //# –– coding:utf-8 – 设置为utf-8

  6. 函数

    1. challable()判断对象是否可以被调用,能被调用的对象就是一个callables对象,比如函数

    2. ascii()调用对象的repr()方法,获得该方法的返回值.ascii() ,函数会将所有非 ascii 字符替换为转义字符:

    3. dir()不带参数时返回当前范围内的变量,方法和定义的类型列表,带参数时返回参数的属性,方法列表。

    4. classmethod()用来指定一个方法为类的方法,由类直接调用执行,只有一个cls参数,执行类的方法时,自动将调用该方法的类赋值给cls.没有此参数指定的类的方法为实例方法。

    5. delattr()删除对象的属性

    6. filter()  过滤器,构造一个序列,等价于[ item for item in iterables if function(item)],在函数中设定过滤条件,逐一循环迭代器中的元素,将返回值为True时的元素留下,形成一个filter类型数据。

      filter(function, iterable)
       
      参数function:返回值为True或False的函数,可以为None。
       
      参数iterable:序列或可迭代对象。
      ​
      def uno(x):
          return x > 10
      v=filter(uno,[1,11,2,45,7,6,13])
    7. iter()

      # 参数二必须是一个可迭代对象,每次调用iterator的next()方法来无
      # 参数的调用o,如果返回值等于参数sentinel,触发StopIteration异常,否则将返回该值。
      
      def a(a):
          pass
      iter(a,[1,2,3,4,])
    8. 三元运算(三目运算)

      v = 成立  if 条件 else 不成立
    9. 函数的模块导入

      #python的第一行是 #!/usr/bin/env python
      # -*- coding:utf-8 -*-
      input()    #输入函数
      print()    #输出函数
      type()     #查看数据类型
      while()   #循环
          pass    #不做任何操作
          break    #终止循环
          continue    #回到循环位置
          
      #编译器:是一步完成在做下一步,如c/c++/c#/java/go。
      #解释器:是一行完成在做下一行,如python/php/ruby。
    10. 深浅拷贝

         import copy     # ying puo 进口 
         v = copy.copy(n)  # kao bei拷贝浅只拷贝可变的
         v = copy.deepcopy(n) # di puo kao bei深拷贝只有在嵌套的时候有用

2.运算符呀

  1. 关系运算符,指定表达式之间的关系,有6种运算关系。

      作用 示例 结果
    < 小于 6<5 false
    > 大于 6>5 true
    <= 小于等于 6<=5 false
    >= 大于等于 6>=5 false
    != 不等于 6!=5 true
    == 恒等于 6==5 false
    • 优先级:同级从左往右。

  2. 算数运算符,对数值型数据进行计算,有5种。

    符号 作用 示例 结果
    + 加法 6+5 11
    减法 6-5 1
    * 乘法 6*5 30
    / 实数除法 6/5 1.2
    // 整数除法 6//5 1
    % 求余 6%5 1
    ** 乘方 6**5 7776
    • 优先级:乘方、乘除、求余、加减

  3. 逻辑运算符,判断真假,有3种。

    符号 作用 示例 结果
    and 与关系 2>5 and 5>4 true
    or 或关系 2>5 or 5>4 true
    not 非关系 2>5 and not 5>4 false
    • 优先级:或、与、非

  4. 赋值运算符,有6种

    符号 作用 示例 结果
    = 等于 a = 5 5
    += 加等于 a +=2 7
    -= 减等于 a -= 2 3
    *= 乘等于 a *=2 10
    /= 除等于 a /=2 2.5
    %= 求余等于 a %= 2 1
  5. 位运算符,按二进制位来计算的,4种

    符号 作用 示例 结果 说明
    & 位与运算 12 & 9 8 按位全一出一
    | 位或运算 12 | 9 13 按位见一出一
    ^ 位异运算 12 ^ 9 5 按位异出一
    ~ 反数加 ~ 12 -13 正负数调转加位,最后一位加1
    << 尾加零 3<< 2 12 前面数转二进制后面数尾部加几个零
    >> 头加零 3>>2 0 前面数转二进制后面数头部加几个零
  6. 成员运算符,属于和不属于,两种

    符号 作用 示例 结果 说明
    in 属于 “1” in “1234” true 1属于1234
    not in 不属于 “1” not in “1234” false 1不属于1234
  7. 身份运算符,身份运算符用于比较两个对象的存储单元

    符号 作用 示例 结果
    is 有相同标识 “a” is “a” true
    is not 没有相同标识 “a” is not “a” true
  8. Python运算符优先级,以下表格列出了从最高到最低优先级的所有运算符:

    运算符 描述
    ** 指数 (最高优先级)
    ~ + – 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@)
    * / % // 乘,除,取模和取整除
    + – 加法减法
    >> << 右移,左移运算符
    & 位 ‘AND’
    ^ | 位运算符
    <= < > >= 比较运算符
    <> == != 等于运算符
    = %= /= //= -= += *= **= 赋值运算符
    is is not 身份运算符
    in not in 成员运算符
    not and or 逻辑运算符

3.基本认识

3.1 编码

  • ascii:不包含中文,早期用于计算机。八位表示字节。

  • unicode :又称万国码,万国码32位表示一个字母(包含全球所有的语言)

  • utf-8:万国码的压缩,虽说32表示一个但不一定都占用,可以用过utf8来去除没用的位。

3.2 变量

  • 随时变化的量被称为变量。

  • 定义变量:a=1 代表a等于1

  • 变量只能有数字、下划线、字母组成,不能用数字开头,不建议用下划线定义变量。一个变量可以赋给多个变量。

  • id(变量):用来查看某个变量,在内存中的地址。

3.3 保注

  • 保留字即关键字,我们不能把它们用作任何标识符名称。Python 的标准库提供了一个 keyword 模块,可以输出当前版本的所有关键字:

    import keyword
    print(keyword.kwlist)
    ​
    #单行注释,开头写
    '''
        多行注释,开头结尾都写
    '''

3.4 缩行

  • 空行

    • 函数之间或类的方法之间用空行分隔,表示一段新的代码的开始。类和函数入口之间也用一行空行分隔,以突出函数入口的开始。

    • 空行与代码缩进不同,空行并不是Python语法的一部分。书写时不插入空行,Python解释器运行也不会出错。但是空行的作用在于分隔两段不同功能或含义的代码,便于日后代码的维护或重构。

    • 记住:空行也是程序代码的一部分。

  • python最具特色的就是使用缩进来表示代码块,不需要使用大括号 {} 。

  • 缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。

  • 实例如下:

    #单行语句
    if True:
        print ("True")
    else:
        print ("False")
    #多行语句
    #Python 通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠(\)来实现多行语句。
    total = item_one + \
            item_two + \
            item_three
  • 多个语句构成代码组

  • 缩进相同的一组语句构成一个代码块,我们称之代码组。

    • 像if、while、def和class这样的复合语句,首行以关键字开始,以冒号( : )结束,该行之后的一行或多行代码构成代码组。

    • 我们将首行及后面的代码组称为一个子句(clause)。

    • print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end=””:

      • print( x, end=” ” )

4.数据类型

  1. python数据类型:数字,字符串,列表,元组,字典

  2. 查看类型的命令:type()

  3. hasattr(),hasattr(object,name)判断对象object是否包含名为name的特性(hasattr是通过调用getattr(object,name))是否抛出异常来实现的。

  4. hash()哈希值hash(object)注意:可哈希的即不可变数据类型,不可哈希即可变数据类型

  5. 如果对象object为哈希表类型,返回对象object的哈希值。哈希值为整数,在字典查找中,哈希值用于快递比价字典的键。

  6. 两个数值如果相等,则哈希值也相等。

  7. help()返回对象的帮助文档,调用内建的帮助系统,如果不包含参数,交互式帮助系统将在控制台启动。如果参数为字串,则可以是模块,类,方法等名称,并且帮助页面将会在控制台打印。参数也可以 。

  8. object(),获取一个新的,无特性(geatureless)对象。Object是所有类的基类。它提供的方法将在所有的类型实例中共享。

  9. 强制转化:dict(),list(),tuple(),int(),str(),bool(),set()

4.1 数值型(Number)

  1. 数字类型:整型,布尔,浮点型,复数型

  2. 将可转为数值的函数:int(),整型:整数表示的范围是2的32次方,正负各占一半。

  3. bool (布尔), 如 True;loat (浮点数), 如 1.23、3E-2;complex (复数), 如 1 + 2j、 1.1 + 2.2j

  4. 函数

    v1 = abs(1)                 # 绝对值
    v2 = float(55)              # 转换为浮点型(小数)
    v3 = max([1,2,3,4,5])       # 找到最大的值
    v4 = min([1,2,3,4,5])       # 找到最小的值
    v5 = sum([1,2,3,4,5])       # 求和
    v6 = divmod(1233,4)         # 两数相除的商和余数
    v7 = bool(1)                # 测试对象是真值还是假值,0是假值,其他都是真值
    # 进制转换
    v8 =bin(15)                 # 将十进制整数转换为二进制,0b代表二进制
    v9 = oct(8)                 # 将十进制整数转换为八进制,0o代表八进制
    v10 = hex(8)                # 将十进制整数转换为十六进制,0x代表十六进制
    v11 = int("0b1101",base=2)  # 将其他进制转换为十进制 参数1是需要转的字符串前面加进制代表,参数2是要转为几进制
    v12 = pow(2,3)              # 几得几次方
    v13 = round(1.127,2)        # 四舍五入,参数2是保留几位小数
    v14 = chr(65)               # 将十进制数字转换成Unicode编码中的对应字符串。
    v15 = ord('A')              # 根据字符在Unicode编码中找到其对应的十进制。
    import random
    v16 = random.randint(65,90) # 模块调用randint生成随机数字
  5. map,循环每个元素(第二个参数),然后让每个元素执行函数(第一个参数),将每个函数执行的结果保存到新的列表中,并返回。

    • 对于参数iterable中的每个元素都应用fuction函数,并将结果作为列表返回。

    • 如果有多个iterable参数,那么fuction函数必须接收多个参数,这些iterable中相同索引处的元素将并行的作为function函数的参数。

    • 如果一个iterable中元素的个数比其他少,那么将用None来扩展改iterable使元素个数一致。

    • 如果有多个iterable且function为None,map()将返回由元组组成的列表,每个元组包含所有iterable中对应索引处值。

    • 第一个参数:必须是一个函数

    • 第二个参数:(可以被for循环)

        map 随机法
        v1[11,22,33,44]
        def func(arg):
            return arg + 100
        result = map(func,v1)#然后将函数的返回值添加到[None,None]
        print(list(result))
        result = map (lambda x:x+100,v1)
          print(result)
        print(list(result))
          filter 挑刺法
          result = filter(lambda x: True if type(x)== int else False,v1)
          print(list(result))
        
          result = filter(lambda x: type(x) ==int ,v1)
          print(list(result))
          reduce 先加法
          import functools
          v1 = ["wo","hao","e"]
          def func(x+y):
              return x+y
          result = functools.reduce(func,v1)
          print(result)
        
          import functools
          v1 = ["wo","hao","e"]
          result = functools.reduce(lambda x,y:x+y,v1)
          print(result)

4.2 字符串(String)

  1. python中单引号和双引号使用完全相同。

  2. 使用三引号(”’或”””)可以指定一个多行字符串。

  3. 转义符 \反斜杠可以用来转义

    1. 在字符串前面添加一个 r,表示原始字符串,不会发生转义。这里的 r 指 raw,即 raw string。

    2. 使用\n代表换行,使用反斜杠()+n转义特殊字符。

    3. 使用\t代表制表符,用于空4格

    4. 使用\‘和\“代表可以在字符串中加入双引号和单引号。

  4. 按字面意义级联字符串,如”this ” “is ” “string”会被自动转换为this is string。

  5. 字符串可以用 + 运算符连接在一起,用 * 运算符重复。

  6. Python 中的字符串有两种索引方式,从左往右以 0 开始,从右往左以 -1 开始。

  7. Python中的字符串不能改变。

  8. Python 没有单独的字符类型,一个字符就是长度为 1 的字符串。

  9. 字符串的截取的语法格式如下:变量[头下标:尾下标:步长]

    print(str[0:-1])           # 输出第一个到倒数第二个的所有字符
    print(str[0])              # 输出字符串第一个字符
    print(str[2:5])            # 输出从第三个开始到第五个的字符
    print(str[2:])             # 输出从第三个开始后的所有字符
    print(str * 2)             # 输出字符串两次
    print(str + 'haaa')        # 连接字符串
  10. 字符串方法中方法前面加is会有不同的返回结果.

  11. 函数

    v1 = "aaaa".upper()    				# 变大写
    v2 = "AAAA".lower()    				# 变小写
    v3 = "aaaa".isupper() 				# 判断是否是大写
    v4 = "AAAA".islower() 				# 判断是否是小写
    v5 = "aaabaa".find("b")				# 找到在字符串中对应值的索引位置,找不到返回-1
    v6 = "123".isdigit()    			# 是数字为True,不是数字False
    v7 = "123".isdecimal()    			# 判断是不是数字
    v8 = "   dsfz".lstrip()    			# 去掉左边的空格
    v9 = "dsfz   ".rstrip()				# 去掉右边的空格
    v10 = " dsfz ".strip()				# 去除两边空格
    v11 = "nxs".replace("x","u",1)		# 替换
    v12 = "nsdxs".split(",",1)			# 分割
    v13 = "nsdxs".rsplit(",",1)			# 右分割
    v14 = len("nsdxs")    				# 计算长度
    v15 = "dfghfh"[1:3:1]				# 索引,三个数第一个是开头数,第二个是结尾数,第三个是跳着取。
    v16 = zip([4,5,6],[1,2,3])			# 将对象逐一配对[(1, 4), (2, 5), (3, 6)]
    v17 = zip(*zip([4,5,6],[1,2,3]))	# 与 zip 相反,*zip([4,5,6],[1,2,3]) 可理解为解压,返回二维矩阵式[(1, 2, 3), (4, 5, 6)]
    stri = "this is string example....wow!!!";
    v18 = stri.startswith( 'is', 2, 4 )	# 只加第一个参数代表是否已什么开头,加了后代表第几个索引开始到第一个索引结束,的范围内寻找.
    v19 = stri.endswith( 'is', 2, 4 )	# 只加第一个参数代表是否已什么结尾,加了后代表第几个索引开始到第一个索引结束,的范围内寻找.
    v20 = "{0},{1}",format("li",1) 		# 占位符
    v21 = "%s,str,%d,int" %("asd",4)	# 占位符
    v22 = "asd".encode("utf-8")			# 用于编码,把unicode转成utf-8存储在硬盘中,默认不加参数,是把str数据转换成bytes类型
    v23 = "asd".decode("utf-8")			# 用于解码,默认不加参数,是把bytes数据转换成str类型
    v24 = ".".join(["a","3","3"])     	# 循环每个元素;并在元素和元素之间加入连接符。
    v25 = "123".rjust(1, '0')			# 字符串右边补零
    v26 = "123".ljust(1, '0')			# 字符串左边补零
    v27 = "123".center(1, '0')			# 字符串左右补零
    v28 = range(1,100,2)    			# 生成数,第三个参数如果数1的话是从左到右,-1是从右到左。
    v29 = "adfg".replace("a","b")    	# 第一个参数是要替换的字符,第二个替换成的字符,替换的个数。
    v30 = "hello word".title()			# 将首字母变成大写
    v31 = "dfghnk".index("n") 			# 判断字符在字符串中的位置(注意如果指定的字符串中找不到会报错)
    v32 = bytes([1,2,3])				# 将一个字符串转换成字节类型4
    v33 = compile("1+2",'<string>', 'eval') # 将字符串编译成python能识别或可以执行的代码,也可以将文字读成字符串再编译。
    """
    compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
        将source编译为代码或者AST对象。代码对象能过通过exec语句来执行或者eval()进行求值。
        参数source:字符串或者AST(abstract syntax trees)对象。
        参数filename:代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。
        参数model:指定编译代码的种类。可以指定'exec', 'eval', 'single'。
        参数flag和dont_inherit:这两个参数为可选参数。
    参数model,用于标识必须当做那类代表来编译;如果是一个代码语句序列组成,则指定exec,如果是单个表达式,则指定eval;如果是一个单独的交互式语句,则指定single。必须要制定,不然肯定会报错。
    """
    s = ["a","b","c"]
    for i ,v in enumerate(s,1):			# 返回一个可以枚举的对象,该对象的next()方法将返回一个元组。
    	print(i,v)						# >>>>>1 a  2 b   3 c
    v34 = complex("1")  				# 当做字符串处理,创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数是字符串,则不需要指定第二个参数
    v34 = exec("12+10")					# 执行字符串或complie方法编译过的字符串,没有返回值
    v35 = eval("1+2") 					#将字符串str当成有效的表达式来求值并返回计算结果,取出字符串中内容
    # pyperclip模块的复制粘贴
    # pip install pyperclip
    import pyperclip as py					
    py.copy("Hello world!")				#复制到剪切板
    print(py.paste())					#如果剪切板有变化就输出
    TODO 用于提示

4.3 列表型(List)

  1. 存储有序\重复的任意类型

  2. 函数

    data = [1,111,1111]
    data.append(11111)    				# 追加
    data.insert(1,12)    				# 指定位置插入元素
    data.remove(12)    					# 值删除
    v = data.pop(1)    					# 索引删除并返回删除的值
    data.clear()    					# 删除全部
    del data[1]   						# 删除索引的值
    data[1]="aa"    					# 修改索引的值
    data.extend(["a",22])			    # 将一个列表里面的值放到另外一个列表中
    data.sort(reverse=True)        		# 将数据按升序或降序排列,True是下降,Fale是上升
    data.reversed()    					# 列表翻转
    sorted(data) 						# 对列表进行临时排序,并不改变列表元素的顺序
    enumerate(data)						# 可以得到列表值、以及值的序号。
    [1,2,3,4,5,6,7][slice(2,5,2)]		# 切片功能
    locals()							# 打印当前可用的局部变量的字典

4.4 元组型(Tuple)

  • 元组tuple,使用圆括号表示,与列表类似,唯一的区别是它的元素不能被修改。

4.5 字典型(Dict)

  1. 字典类型包括键和值,并且使用大括号表示,键值对的添加顺序没有关系,存储的键值对的关联关系。

  2. 函数

    data = {"k1":"v1"}
    data.keys()						    # 获取所有键
    data.values()    					# 获取所有值
    data.items()					    # 获取所有键和值
    data.get("k1",13)				    # 判断特定的值是否在字典中,不在默认返回None
    data.update()					    # 更新
    del data["k1"]						# 使用del命令来进行删除字典中的键值对,被删除的键值对永远的消失了。
    data.sorted(reverse=True)   		# 降序排列,括号中加上reverse=True,将会变成升序。
    data.setdefault("k1", "123")		# 有两个参数主要用于判断键是否在某个字典中。

4.6 集合型(Set)

  1. 集合是无序和无重复的

  2. 函数

    frozenset()							# 创建一个不可修改的集合。
    set() 								# 一样
    # set和frozenset最本质的区别是前者是可变的,后者是不可变的。当集合对象会被改变时(例如删除,添加元素),只能使用set,
    # 一般来说使用fronzet的地方都可以使用set。
    # 参数iterable:可迭代对象。    
    data = set(1,2,3,4,5,6,7)
    data.add(8)							# 添加 
    data.discard(1)						# 删除  
       
    data.intersection({1,"李少妻","小黑"})#(交集)v1和v2里面都有的
    data.union({1,"李少妻","小黑"})		 #(并集)v1和v2里面全部的
    data.difference({1,"李少妻","小黑"})	 #(差集)v1里面没有的
    data.symmetric_difference({1,"李少妻","小黑"})# (对称差集)
  3. 集合(嵌套):列表\字典\集合都是可变的不能嵌套

4.7 布尔型(Bool)

  • True、False

4.8 数组

  1. 函数

    import scipy.io as sio
    a = np.ones((2, 3, 4, 5)) 				# 以下都省略 import numpy as np
    a.shape									# 查看数组维数的大小。
    b = np.transpose(a,(3, 2, 1, 0))  		# 改变数组维数的位置,如把3*5的矩阵变成5*3,每个数字表示a数组所在的维数位置,如3表示把a中最后一维换到b的第一维
    c = sio.loadmat('x_data_6_for_mxnet.mat')	# 加载.mat文件(matlab数据格式),特别适合高维的.mat文件。
    
    dict = {'a' : 'apple', 'b' : 'banana', 'g' : 'grape', 'o' : 'orange'}
    a_value = dict['a']						# 取dict中的一个value。
    a_value
    
    a.size									# 查看数组的元素个数。
    
    from mxnet import nd
    x = nd.array([3.0])
    x.asscalar()							# 转换ndarray数据(mxnet中的数据)为python数据。
    seasons = ['Spring', 'Summer', 'Fall', 'Winter']
    list(enumerate(seasons))				# 用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

5.文件操作

  1. open,打开、close,关、read,读、write,写、seek,调整光标的位置、readlines,每一行分割

  2. 只读只写字符串(r、w、a)、可读可写字符串(r+、w+、a+)、只读只写二进制(rb、wb、ab)、可读可写二进制(r+b、w+b、a+b)

    f = open('美女模特空姐护士联系方式.txt',mode='r',encoding='utf-8')
    content = f.read()
    print(content)
    f.close()
    
    f = open('美女模特空姐护士联系方式.txt',mode='w',encoding='utf-8')
    content = f.write(b"nihao")		#是以二进制储存
    print(content)
    f.close()
    
    f = open("a.txt",mode="wb")
    data = "我好空"
    content = data.encode("utf-8")
    f.write(content)
    f.close
  3. tell,获取当前光标所在的字节位置、flush,强制把内存里面的东西刷到硬盘上

  4. 简便方式

    #青年方式
    # replace 替换
    with open("a.txt",mode="r",encoding = "utf-8") as f1:
        data = f1.read()
    new_data = data.replace("飞沙","666")
    print(new_data)
  5. 保存变量

    # shelve保存变量
    import shelve
    shelfFile = shelve.open("mydata")
    shelfFile["cats"] = ["alex","wupeiqi"]			#加一次使用时直接打开索引即可,cats就是键。
    shelfFile["cats"]
    shelfFile.close()
    
    # pprint.pformat保存变量
    import pprint
    cats = [{"name":"alex","desc":"chubby"}]
    pprint.pformat(cats)
    fileObj = open("myCats.py","w")
    fileObj.write("cats = "+pprint.pformat(cats)+"\n")
    fileObj.close()
    
    import myCats
    myCats.cats
    myCats.cats[0]
  6. 大文件可以用这种方法

    f1 = open("a.txt",mode="r",encoding="utf-8")
    f2 = open("b.txt",mode="w",encoding="utf-8")
    for i in f1:
        n = i.replace("nihao","nisi")
        f2.write(n)
    f1.close()
    f2.close()
  7. 三元运算(三目运算)

    # v = 成立  if 条件 else 不成立
    data = input(">>>")
    value = ing(data) if data.isdecimal() else None

6.用函数呀

  1. 截至目前:面向过程编程。【可读性差/可重复性差】。

  2. 写代码的方式:面向过程–>函数式编程–>面向对象编程

  3. 本质:将n行代码拿到别处并给起个名字,以后通过名字就可以找到这段代码被执行。

  4. 场景:代码重复执行,代码量特别多超过一屏,可以选择通过函数进行代码的分割。

    def send_email():    
        import smtplib
        from email.mime.text import MLMEText
        from email.utils import formaddr
    
        msg = MIMEText('信息',"plain","utf-8")
        msg["From"] = formataddr(["发件人","xxxxxx@163.com"])
        msg["To"] = formataddr(["收件人","xxxxxxxx@qq.com"])
        msg["Subject"] = "标题"
    
        server = smtplib.SMTP ("smtp.163.com",25)
        server.login("xxxxxx@163.com","密码")
        server.sendmail("xxxxxx@163.com",["xxxxxxxx@qq.com",],msg.as_string())
        server.quit()
    
    user_input = input("请输入角色:")
    
    if user_input =="管理员":
        send_email()
    elif user_input =="管理员":
        send_email() 
    elif user_input =="管理员":
        send_email()
  5. 函数的基本结构 and 参数

    def nnn(u):
        n[11,22,33,44]
        print(n[u])
    nnn(0)
    
    def func(max_range):
        result = []
        while True:
            if len(result) ==0:
                result.append(1)
            elif len(result) == 1:
                result.append(1)
            else:
                val = result[-1] + result[-2]
                if val > max_range:
                    dreak
                result.append(val)
        return result
    
    v = func(100)
    print(v)
    
    def write_file(file_path,content="\n"): 	#换行
    def read_file(file_path,num=1): 	#只读第一行
        
    def fuync(*args):		#*args 可以传n个参数
        print(args) 		#传的值是元组
    
        func(1)
        func(1,2)
        func(1,2,3)
        
    def fuync(*args):		#*args 可以传n个参数
        print(args)
    
    func((11,22,33,44,55))
    func(*(11,22,33,44,55))  
    
    def fuync(**kwargs):		#**kwargs 只能是指定传参
        print(kwargs) 		#它传的参是字典
    
    func(k1=1,k2=2)
    func(**{"K1":"V2","K2":"V3"})
    
    def fuync(*args,**kwargs):	
        print(args,kwargs) 		
    
    func(1,2,3,4,5,{"K1":"V2","K2":"V3"})
    
    #如果要想给value设置默认值是空列表
    #不推荐
    def func(data,value=[]):
        pass
    #推荐
    def func(data,value=None):
        if not value:
            value = []
            
    #补充:对于函数的默认值慎用可变类型。   
  6. getattr()  获取对象的属性

    getattr(object, name [, defalut])
    """
        获取对象object名为name的特性,如果object不包含名为name的特性,将会抛出AttributeError异常;如果不包含名为name的特性
        且提供default参数,将返回default。
        参数object:对象
        参数name:对象的特性名
        参数default:缺省返回值
    """

6.1 全与局变量

  1. global,找全局里面的数据;nonlocal,找上一级的数据

    name = "老男孩"
    def func():
        name = "alex"
        def inner():
            global name
            print(name)
            name = 999
        inner()
        print(name)
    func()
    
    name = "老男孩"
    def func():
        name = "alex"
        def inner():
            nonlocal name
            print(name)
            name = 999
        inner()
        print(name)
    func()

6.2 匿名函数呀

  1. 用lambda来实现的

    #定义一个简单的函数将他赋给func5传入两个值进行判断。
    func5 = lambda n1, n2: n1 if n1 > n2 else n2
    v = func5(7, 1)
    print(v)
    
    def func5(n1,n2):
        if n1>n2:
            return n1
        else:
            return n2
    v = func5(5,3)
    print(v)
    
    v = []
    def f(x):
        b = v.append(x)
        return b
    n = f("nnnnnnn")
    print(n)
    
    f = lambda x:x.split("l")
    v1 = f("alex")
    print(v1)
  2. 函数可以做返回值

    def func():
        print(123)
    def dar():
        return func
    v =dar()
    print(v())

6.3 快用闭包呀

  1. 闭包是用到函数可以返回函数的特性所实现的

    #不是闭包
    def func1(name):
        def inner1():
            return 123
        return inner
    #是闭包:封装值+内层函数需要使用。
    def func1(name):
        def inner2():
            print(name)
            return 123
        return inner

6.4 用作用域呀

  • 递归,函数自己调用自己。(效率低)

    def func():
        print(1)
        func() 
    func()
    
    def func(i):
        print(i)
        func(i+1)
    func(1)
    #递归次数最大1000
    #在cmd里打开python解释器,调用sys模块(import sys),查看所有(dir(sys)),找到getrecursionlimit并调用(sys.getrecursionlimit())
  • 函数执行的流程分析(函数到底是谁创建的?)

  • 闭包概念:为函数创建一块区域并为其维护自己数据,以后执行时方便调用。[应用场景:装饰器/SQLAIchemy源码]

7.练习题呀

  1. 翻页

    '''
    要求:
        每页显示10条数据
        让用户输入要查看的页面:页码
    '''
    
    user_list = []
    for i in range(1,836):
        temp = {"NAME":"你李少妻-%s" %i,"email":"123%s@qq.com"%i }
        user_list.append(temp)
    
    #数据总条数
    total_count = len(user_list)
    
    #每页显示10条
    per_page_count = 10
    
    #总页码数
    max_page_num,a = divmod(total_count,per_page_count)
    if a>0:
        max_page_num += 1
    
    while True:
        pager = int(input(">>>"))
        if pager <1 or pager > max_page_num:
            print("页码不合法,必须是1~%s" %max_page_num)
        else:
            start = (pager-1) * per_page_count
            end = pager * per_page_count
            data = user_list[start:end]
            for item in data:
                print(item)
  2. 将ip转换为二进制在转换为十进制

    def transformation_ip(ip):return [(bin(int(i)).replace("0b","").rjust(8,"0")) for i in ip.split(".")]
    print(transformation_ip(input(">>>"))[0])

中级阶段

1.基本使用

  1. 主文件

    if __name__ == "__main__"
    	page.pager()
  2. 如果你想将a和b的值调换,python有一个写法

    a=1
    b=2
    a,b = b,a
  3. 斐波那契数列

    num1 = 0
    num2 = 1
    while True:
      	print(num2)
        num1,num2 = num2,num1+num2
  4. 对于包的定义:

    1. py2:文件见中必须有__ init __.py。

    2. py3:不需要__ init __.py

    3. 推荐大家以后写代码时,都要加上此文件。

2.用模块呀

  1. 模块基本知识

    1. 内置模块,python内部提供的功能。

      import sys
      print(sys.atgv)
    2. 第三方模块,下载/安装/使用。

      #把pip.exe所在的目录添加到环境变量中。
      #https://pypi.org
      pip install 要安装的模块名称  #pip install xlrd
      模块会被安装到c:/python39/lib/site-packages
    3. python36 -m pip install –upgrade pip

  2. 自定义模块

    # xxx.py
    
    def f1():
        print("f1")
        
    def f2():
        print("f2")
    # r1.py
    #掉用自定义模块中的功能
    import xxx
    xxx.f1()
    xxx.f2()
  3. 导入模块

    import abc
    from abc import asc
    from abc import *
    from abc import asc as a
  4. 模块路径

    import os
    import sys
    base_dir = os.path.dirname (os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(base_dir)

2.1 md5

  1. 将字符串加密

    def get_md5(data)
    	import hashlib		#hai si lei buo
    	obj = hashlib.md5()  #md5 加密
    	obj.update(data.encode("utf-8"))	#要加密的字符串,以压缩格式
    	result = obj.hexdigest()
        return result
  2. 加盐

    def get_md5(data)
    	import hashlib		#hai si lei buo
    	obj = hashlib.md5("sdfjsdkljg".encode("utf-8"))  #md5 加密,默认在想要加密的前面加上MD5后面的字符串
    	obj.update(data.encode("utf-8"))	#要加密的字符串,以压缩格式
    	result = obj.hexdigest()
        return result
  3. 示例

    import hashlib
    user_list = []
    def get_md5(data)			
    	obj = hashlib.md5("sdfjsdkljg".encode("utf-8"))  
    	obj.update(data.encode("utf-8"))
    	result = obj.hexdigest()
        return result
    
    def register():
        print("请创建账户")
        while True:
    		user = input("请输入用户名")
            if user =="n":
                return
            pwd = input("请输入密码")
            temp = {"username":user,"password":get_md5(pwd)}
            user_list.append(temp)
    def login():
    	print("用户登录")
        user = input("请输入用户名:")
        pwd = input("请输入密码:")
        
        for item in user_list:
            if item["username"] == user and item["password"] == get_md5(pwd):
                return True
    register()
    result = login()
    if result:
        print("成功")
    else:
        print("失败")
  4. 密码不显示(只能在终端中用)

    import getpass    #gai te pa si
    pwd = getpass.getpass("请输入密码:")
    if pwd == "123":
        print("正确")

2.2 $sys

  1. 基本使用

    import sys 
    
    sys.argv()							# 显示文件名
    sys.path()							# 默认python去导入模块时,会按照sys.path中的路径挨个查找,sys是解释器相关的数据:递归次数/引用次数
    
    sys.exit(0)    						# sys模块里的exit方法,作用终止程序
    
    a = [11,22,33]
    B = a
    print(sys.getrefcount(a))			# a被调用的次数,获取一个值的应用计数
    
    v1 = sys.getrecursionlimit()		# python默认支持的递归数量
    
    sys.stdout.write("sdfjl")
    print("sdjfl\r",end="")				# \n 换行、\t 制表符、\r 回到当前行的起始位置 
    
    import time
    for i in range(1,101):
        msg = "%s%%\r" %i
        print(msg,end="")
        time.sleep(0.05)    			# 然程序在这多执行0.05秒
  2. 模块参数

    import sys
    #获取用户执行脚本时,传入的参数。
    #c:\sjldj\sldjf.exe d:/djks/dslkf/d.py d:/sdklf
    #sys.argv = [d:/djks/dslkf/d.py ,d:/sdklf]
    path = sys.argv[1]
    import shutil
    shutil.rmtree(path)#删除path的所有文件
    sys.path

2.3 $$os

  1. 基本使用

    import os
    
    os.stat(file_path).st_size			# 获取文件大小
    v = r"d:\code\ksd.mp4" 				# r是转义,遇到\n\t\r当作普通的字符串处理
    os.listdir(path)					# 查看一个目录下所有的[第一层]
    os.walk(path) 						# 查看一个目录下所有的[所有层]
    os.remane("name","name2")			# 重命名
    os.mkdir(path)						# 创建目录
    os.makedirs(path)					# 创建文件夹
    os.getcwd()							# 获取当前路径
    os.chdir(path)						# 修改当前路劲
    os.listdir(path)					# 查看路径下的所有文件	
    # os.path.xxx()						# os.path下的方法
    os.path.join(path,path,path)		# 路径拼接
    os.path.abspath(path)				# "."代表当前的绝对路径,".\\path"代表当前的相对路径,返回path规范化的绝对路径。 
    os.path.isabs(path)					# 查看一个路劲是相对路径还是绝对路径,绝对True。
    os.path.relpath(path,start)			# 将绝对路径转为相对
    os.path.basename(path)				# 获取路径中的最后一段
    os.path.dirname(path)				# 获取路径中除最后一段的所有路劲
    os.path.split(path)					# 将路径分割
    os.path.getsize(path)				# 查看路径中文件的字节大小
    os.path.exists(path)				# 查看路径是否存在
    os.path.isfile(path_file)			# 查看文件是否存在并且是一个文件
    os.path.isdir(path)					# 查看路径是否存在并且是一个文件夹
    os.path.exists(path)				# 查看路径的闪存盘是否于电脑连接
    os.path.commonprefix(list_path)		# 返回列表元素中共有路径
    os.path.normcase(path) 				# 在Linux和Mac下,该函数会原样返回path,在win下会将路径中所有字符转换为小写,并将所有斜杠转换为饭斜杠
    os.path.normpath(path)				# 规范化路径
    os.path.splitdrive(path)			# 返回元组,元组两个元素盘符和路径。
    os.path.splitext(path_file)			# 返回元组,元组两个元素路径和扩展名。
    os.path.getatime(path)				# 文件或者目录的最后存取时间
    os.path.getmtime(path)				# 文件或者目录的最后修改时间

2.4 shutil

  1. 基本使用

    import shutil
    
    shutil.rmtree("test")					# 删除目录
    shutil.move("zz","bb")					# 重命名
    shutil.make_archive("zzh","zip","b:\")	# 压缩文件
    shutil.unpack_archive("zzh.zip",extract_dir=r"b:\",format="zip") # 解压文件
  2. 练习题

    import os
    import shutil
    from datetime import dateime
    ctime = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
    
    #1/压缩lizhongwei文件夹 zip
    #2/放到code目录(默认不存在)
    #3/将文件解压到d:\x1目录中。
    
    if not os.path.exists("code"):
        os.makedirs("code")
    shutil.make_archive(os.path.join("code",ctime),"zip","d:\code\slkj\lizhongwei")
    
    file_path = os.path.join("code",ctime)+".zip"
    shutil.unjpack_arbhive(file_path,r"d:\x1","zip")

2.5 time

  1. UTC/GMT:世界时间;本地时间:本地时区时间。

  2. 基本使用

    import time
    
    time.time()					# 时间戳:1970-1-1 00:00
    time.sleep(10),等待秒数。
    							# ##############获取datetime格式时间
    v1 = datetime.now() 		# 当前本地时间
    							# 当前东7区时间
    tz = timezone(timedelta(hours=7))
    v2 = datetime.now(tz)
    v3 = datetime.utcomw()		#当前UTC时间
    							# ##########把datetime格式转换成字符串
    v1 = datetime.now()
    val = v1.strftime("%Y-%m-%d %H:%M:%S")
    							# ##############字符串转成datetime
    v1 = datetime.strptime("2011-11-11","%Y-%m-%d")
    							# #################datetime时间的加减
    v1 = datetime.strptime("2011-11-11","%Y-%m-%d")
    v2 = v1 - timedelta(days=140)
    date = v2.strftime("%Y-%m-%d")
    							# ############### 时间戳和datetime关系
    ctime = time.time()
    v1 = datetime.fromtimestamp(ctime)
    
    v1 = datetime.now()
    val = v1.timestamp()

2.6 json

  1. json是一个特殊的字符串,

  2. json和pickle

    1. json,优点:所有语言通用;缺点:只能序列化基本的数据类型list/dict/int…

    2. pickle,优点:python中所有的东西都被他序列化(socke对象);缺点:序列化的内容只有python认识。

    3. loads,字符串转换回

      v = {1,2,3,4}
      val = pickle.dumps(v)
      print(val)
      data = pickle.loads(val)
      print(data,type(data))
  3. 基本使用

    import json
    
    v = {1,2,3,4}
    f = open ("x.xt",mode="wb")
    val = pickle.dump(v,f)				# 第一个转换第二个写入
    f.close
    # ##################################
    f = open ("x.xt",mode="rb")
    data = pickle.load(f)				# 转换并读出
    f.close
      
    v = [12,3,4,{"k1","v1"},True,"asdg"]
    v1 = json.dumps(v)					# 序列化,将python的值转换为json格式的字符串。
    
    v = "[3,4,{"k1","v1"},True,"asdg"]"
    v1 = json.loads(v)					# 反序列化,将python的值转换为json格式的字符串。
  4. 示例

    import requests
    import json
    
    response = requests.get("https://wwww sdl.com")
    data = json.loads(response)
    print(type(data))
    print(data)
    # ###############################
    import requests
    
    response = requests.get("https://www.runoob.com/python3/python3-tutorial.html")
    print(type(response))
    print(response)
    with open("b.html", mode="wb",)as f:
        for i in response:
            f.write(i)

3.用三器呀

3.1 装饰器

  1. 装饰器:在不改变原函数内部代码的基础上,在函数执行之前和之后自动执行某个功能。

  2. 函数伪装装饰器

    def func(arg): 					#创建函数func并传参arg
        def inner(): 				#在func函数里面创建函数inner
            print("before") 		 #在inner里面打印字符串"before"
            v = arg()				#将arg里面的函数运行并赋给v
            print("after")			#在inner里面打印字符串"after"
            return v 				#在inner里面返回v的值
        return inner				#在func里面返回inner
    #装饰器就是在不改变index的值的情况下添加"before"和"after"
    def index():					#创建函数index
        peint("123")				#在函数index里面打印"123"字符串
        return "666"				#在index里面返回字符串"666"
    index = func(index)				#调用func函数并传入index函数
    index()						   #调用index函数
  3. 真正的装饰器

    def func(arg): 					
        def inner(): 				
            print("before") 		
            v = arg()				
            print("after")			
            return v 				
        return inner
    #第一步:执行func函数并将下面的函数参数传递,相当于:func(index)
    #第二步:将func的返回值重新赋值给下面的函数名。index = func(index)
    @func	#装饰器
    def index():					
        peint("123")				
        return "666"								
    index()		
    
    def x(func):
        def inner():
            return func()
        return inner
    @f
    def index():
        pass
    
    # ######################################
    							# 然你理解没意义的一段代码
    def x(func): 				# 2 运行x函数并创建inner函数
    	def inner(a1,a2):		# 5 运行inner函数并传入两个值
            return func()		# 6调用func函数就是index函数
        return inner 			# 3 返回inner函数并将
    							# inner赋给index(index = innder)
    @x 							# 1 0调用x函数并吧index当做参数传给x
    def index():				# 7 运行index函数
        pass
    index(1,2) 					# 4 调用index函数index就是inner函数并传入两个实参
    
    # 不管有几个参数都可以用的装饰器
    def x1(func):
        def inner(*args,**kwargs):
            return func(*args,**kwargs)
        return inner
    
    @x1(1)
    def f1():
        pass
    @x1
    def f2(a1):
    pass
  4. 装饰器建议写法:

    def x1(func):
        def inner(*args,**kwargs):
            data = func(*args,**kwargs)
            return data
        return inner
  5. 示例

    #如何查看一个路径是否存在?
    import os
    result = os.path.exists("路径地址")
    
    # result为True,则表示路径存在。
    # result为False,则表示路径不存在。
    # ######################################
    def wrapper(func):
        def inner(*atgs,**kwargs):
            #检测路径是否存在
            path = args[0]
            #路径不存在就执行判断下面命令
            if not os.path.exists(path):
                print("路径不存在")
                return None
            result = func(*atgs,**kwargs)
            return result
        return inner
    @wrapper
    def read_userinfo(path):
        file_obj = open(path,mode="r",encoding="utf-8")
        data = file_obj.read()
        file_obj.close()
        return data
    
    content = read_userinfo("/usr/bin/xxx/xxx")
    print(content)
    
    
    import time
    
    def wrapper(func):
        def inner():
            start_time = time.time()    #获取当前时间
    	    v = func()
    		end_time = time.time()    #获取当前时间
    		print(start_time-end_time)
    		return v
        return inner
    
    @wrapper
    def func1():
        time.sleep(2) 	#等待两秒时间
        print(123)
        
    
    def func2():
        time.sleep(1) 	#等待两秒时间
        print(123)
    
    def func3():
        time.sleep(1.5) 	#等待两秒时间
        print(123)
    func1()
    
    
    #加参数
    def func(arg): 					
        def inner(*args,**kwargs): 				
            print("before") 		
            v = arg(*args,**kwargs)				
            print("after")			
            return v 				
        return inner
    @func
    def index():					
        peint("123")				
        return "666"								
    index("yidn")					   

3.2 迭代器

  1. 迭代器,帮助你对某种对象(str/list/tuple/dict/set类创建的对象)中的元素进行逐一获取。

    v1 = iter([11,2,2,3,])			# 列表转换成迭代器
    v2 = v1.__iter__()		
    v2.all()						# 接受一个迭代器,如果迭代器里有一个元素为真,那么返回True,否则返回False
    v2.any()						# 接受一个迭代器,如果迭代器里有一个元素为真,那么返回True,否则返回False
    try:
    	val = v1.__next__()			# 反复调用,迭代器想要获取每个值
    except Stoplteration as e:		# 直到报错:Stoplteration错误,表示已经迭代完毕
            pass
  2. 如何判别一个对象是否是迭代器:内部是否有__ next__方法。

  3. 可迭代对象是内部具有__ iter__()方法并且可以被for循环。

3.3 生成器

  1. 生成器函数(内部是否包含yield)

    def func():
    	print("你好")
    	yield 1
    	print("1")
    	yield 2
    	print("3")
    	yield(3)
    	print("4")
    
    # 函数内部代码不会执行,返回一个生成器对象。
    v1 = func()
    #生成器是可以被for循环,一旦开始循环那么函数内部代码就会开始执行。
    for item in v1:
    	print(item)
    #################################################################
    count = 1
    def func():
        while True:
            yield count
    	count += 1
    
    val = func()
    for item in val:
        print(item)
  2. 示例

    def func():
        """ 
        分批去读取文件中的内容,将文件的内容返回给调用者。
        :return:
        """
        cursor = 0
        while True:
            f = open("dd",'r',encoding = "utf-8")
    	f.seek(cursor)
    	data_list[]
    	for i in range(10):
    	    ilne = f.readline()
    	    if not line:
    	        return
    	    ata_list.append(line)
            cursor = f.tell()
    	f.close()
        for row in data_list:
            yield row
  3. 总结:

    1. 函数中如果存在yield,那么该函数就是一个生成器函数,调用生成器函数会返回一个生成器,生成器只有被for循环时,生成器函数内部的代码才会执行,每次循环都会返回执行。

    2. 迭代器,对可迭代对象的元素进行逐一获取,迭代器对象的内部都有一个next方法,用于以一个个获取数据。

    3. 生成器,函数内部有yield则就是生成器函数,调用函数并返回一个生成器,循环生成器时,则函数内部代码才会执行。

4.推导式呀

  • 列表推导式

    vals = [i for i in "alex"]
    v1 = [i for i in "alex"]
    v2 = [i+100 for i in range(10)]
    v3 = [ 99 if i>5else 66  for i in range(10)]
    
    def func():
        print(123)
    v4 = [func for i in range(10)]
    
    v5 = [lambda :100 for i in range(10)]
    
    def num():
    	return [lambda x:i*x for i in range(4)]
    print([m(2) for m in num()])
    
    v9 = [i for i in range(10) if i > 5]
  • 集合推导式

    v1 = { i for i in "alex"}
  • 字典推导式

    v1 = {"k"+str(i):i for i in range(10)}

5.异常处理

  1. 基本使用

    def func(c):
        try:
            return a.strip()
        #e里面保存的是报错信息
        except Exception as e:
            pass
        return False
    
    v = func("alex")
    if not v:
        print("函数执行失败")
    else:
        print("结果是",v)
  2. 练习题

    # 1.写函数,函数接受一个列表,请将列表中的元素每个都 +100
    def func(arg):
        result = []
        for item in arg:
            if item.isdecimal():
                result.append(int(item)+100)
        return result
    # 2.写函数去,接受一个列表。列表中都是url,请访问每个地址并获取结果。
    import requests
    def func(url_list):
        result = []
        try:
        	for url in url_list:
                response = requests.get(url)
                result.append(response.text)
        except Exception as e:
            pass
        return result

6.面向对象

  1. 类和对象,类是具有相同属性的摸具,对象有摸具创造具有相同的属性和方法。

  2. 三大特性,封装、继承、多态,python原生支持多态,崇尚鸭子模型。由于python函数传参时,无序指定类型:

    def func(arg):# arg可以是多种类型,只要其中有send方法即可。
    	arg.send()
  3. 编写面向对象程序,归类+提取公共值

  4. self到底是谁,self参数是python帮助我们自动传递(就是自己)。

  5. 如果执行面向对象中的方法时,前面需要有一个对象:xxx.func()

    class Foo:
        def f1 (self):
            pass
        def f2(self):
            self.f1()
    obj = Foo()
    obj.f1()
  6. python支持多继承

    def __init__(self,name):	#构造方法
  7. 经典类和新式类

    • 新式类在py2中,如果自己的前辈要有人继承object,那么此类就是新式类。

    • py3经典类和新式类的查照成员的顺序不一致。

      # 经典类是一条道走到黑(深度优先),会按照继承关系,先在自己这寻找,找不到后去父类中找,只找继承父类的第一个,直到第一代,会回来再去找第二个父类。
      print(Foo.__mrc__) 		# 新式类是由c3算法实现
  8. 基本使用

    class abc(obj):
    	def func(self,name):
            print(name)
            return 123
        def func2(self,name):
            print(name)
            return 456
    #调用类中的方法
    obj = abc()					#1.创建该类的对象
    result = obj.func("alex")	#2.通过对象调用方法
    print(result)
  9. 对象的作用,存储一些值,以后方便使用。

    class File:
        def read(self):
            with open(self.xxxx,mode="r",encoding="utf-8") as f:
                data = f.read()
            return data
    
        def write(self,content):
            with open(self.xxxx,mode="w",encoding="utf-8") as f:
                data = f.write(content)
    
    #实例化了一个File类的对象
    obj1 = File()
    #在对象中写了一个xxxx = "test.log"
    obj1.xxxx = "test.txt"
    #通过对象调用类中的read方法,read方法中的self就是obj。
    obj1.write("alex")
    obj1.read()
    
    class Person:
        #初始化方法(构造方法),给对象的内部做初始化。
        def __init__(self,n,a,g):
            self.name = n
            self.age = a
            self.gender = g
    
        def show(self):
            temp = "我是%s,年龄%s,性别%s" % (self.name,self.age,self.gender,)
            print(temp)
    
    #类()实例化对象,自动执行此类中的__init__方法。
    p1 = Person("里",12,"男")
    p1.show()
  10. 总结:将数据封装到对象,方便使用。

6.1 成员三类

  1. 说明

    class Foo:
        #方法
        def __init__(self,name):
            #实例变量/字段
            self.name = name
        #方法
        def func(self):
            pass
        
        # obj,Foo类的对象
        # obj,Foo类的实例
        obj = Foo("holle") 

1.变量

  1. 实例变量(字段),公有和私有实例变量(字段)

    class Foo:
        def __init__(self,name):
            self.__name = name				# 私有实例变量,就是在变量前面加上两个下划线(私有字段)
            self.age = 123
        def func(self):
            print(self.__name)
    
    obj = Foo("holle")
    print(obj.__name)						# obj.__name 无法访问
    obj.func()    							# 找个人内部的人访问
  2. 类变量(静态字段),公有和私有类变量(静态变量)

    class Foo:
    	#类变量(静态字段)
    	country = "中国"
    	def __init__(self,name):
    		#实例变量(字段)
    		self.name = name
              
    obj1 = Foo("holle")
    obj2 = Foo("你好")
  3. 准则

    1. 实例变量(字段)访问时,使用对象访问,即:obj1.name

    2. 类变量(静态字段)访问时,使用类访问,即:Foo。country实在不方便时,(才使用对象)

    3. 什么时候用类变量?当所有对象中有共同的字段时则要改都改要删都删时,可以将 实例变量(字段)提取到 类变量(静态字段)

2.方法

  1. 实例方法

    class Foo(object):
        def __init__(self,name):
            self.name = name
        
        #实例方法
        def func(self):
            print(self.name)	
  2. 静态方法

    class Foo(object):
        #静态方法,如果方法无需使用对象中封装的值,那么就可以使用静态方法
        @staticmethod
        def display():
            print("666")
    Foo.display()
  3. 类方法

    class Foo(object):
        @classmethod
        def show(cls,x1,x2):
            print(x1,x2)
    Foo.show(1,8)
  4. 总结

    1. 定义时:方法上方写:@classmethod,方法的参数:至少有一个cls参数

    2. 执行时:类名.方法名() #默认会将当前类传到参数中。

    3. 什么时候用?如果在方法中会使用到当前类,你们就可以使用方法。

3.属性

  1. 写法

    class Foo(object):
        @property
        def start(self):
            return 1
        
        @proprety
        def end(self):
            return 10
        
    obj = Foo()
    print(obj.start)
    print(obj.end)
    
    class Foo(object):
        def __init__(self,age):
            self.age = age
            
        def display(self):
            print(self.age)
            
    data_list = [Foo(8),Foo(9)]
    for i in data_list:
        #在print的时候先执行方法,在执行对象
        print(i.display(),i.age)
  2. 总结:

    1. 编写时:方法上方写@property,方法参数:只有一个self

    2. 调用时:无序加括号 对象.方法

    3. 应用场景:对于简单的方法,当无需传参则有返回值时,可以使用@property

6.2 其他成员

  1. 主动调用其他类的成员

    # Base.实例方法(自己传self),与继承无关
    class Base(object):
        def f1(self):
            print("5")
    
    class Foo(object):
        def f1(self):
            print("3")
            Base.f1(self)
            
    obj = Foo()
    obj.f1()
    
    # 按照类的继承顺序
    class Base(object):
        def f1(self):
            print("5")
    
    class Foo(Base):
        def f1(self):
            print("3")
            super().f1()		# 找下一个同名方法
            
    obj = Foo()
    obj.f1()
    ###########################
    class Foo(object):
        def f1(self):
            super().f1()
            print("5")
    
    class Bar(Base ):
        def f1(self):
            print("3")
            
    class Info(Foo,Bar):
        pass
            
    obj = Info()
    obj.f1()
  2. 特殊成员

    class Foo(object):
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
        def __call__(self,*args,**kwargs):
            print(111,args,kwargs)
            
        def __getitem__(self,item):
            print(item)
            return 8
        def __setitem__(self,key,value):
    		print(key,value,111)
        def __delitem__(self,key):
            print(key)
        def __add__(self,other):
            return self.a1 + other.a2 
        def __enter__(self):
            print(1111)
            return 999
        def __exit__(self,exc_type,exc_val,exc_tb):
            print(2222)
    # 1.类名() 自动执行__init__
    obj = Foo(1,2)
    # 2.对象() 自动执行__call__
    obj(5,2,k1=122)
    #3.对象[xx] 自动执行__getitem__
    ret = obj["yu"]
    print(ret)
    #4.对象["xx"] = 123 自动执行__setitem__
    obj["k1"]=123
    #5.del 对象["sss"] 自动执行__delitem__
    del obj["uuu"]
    #6.对象+对象       自动执行__add__
    obj1 = Foo(1,2)
    obj2 = Foo(88,99)
    ret = obj2 = obj1
    print(ret)
    #7.with 对象    自动执行__enter__进入,__exit__退出
    obj = Foo
    with obj as f:
        print(f)
        print("内部")
    
    # #################################
    #8.真正的构造方法
    class Foo(object):
        def __init__(self,a1,a2):#初始化方法
        	self.a1 = a1
        	self.a2 = a2
        def __new__(cls,*args,**kwargs):#构造方法
            v1 = object.__new__(cls)#python内部创建一个当前类的对象(创建时内部是空的)。
            print(v1)
            return v1
    
    obj = Foo(1,2)
    print(obj)
    
    class Foo(object):
        def __init__(self):
            pass
        def func(self):
            pass
        #查看obj时返回"F1"
        def __str__(self):
            return "F1"
        
    obj = Foo()
    print(obj,type(obj))  
    
    class Foo(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def func(self):
            pass
        def __iter__(self):
            return iter([11,22,33,4])
    """
    如果想要把不可迭代对象 -> 可迭代对象
    1.在类中定义__iter__方法
    2.iter 内部返回一个迭代器
    """ 
    obj = Foo("楼上的",99)
    for item in obj1:
        print(item)
        
    _ _dict _ _   # 获取封装值  
    _ _doc _ _    # 打印类注释

6.3 类的有关

  1. issubclass and isinstance

    class Base(object):
        pass
    class Foo(Base):
        pass
    class Bar(Foo):
        pass
    
    print(issubclass(Bar,Base))			# 检查第一个参数是否是第二个参数的子类,是True,不是False
    obj = Foo()
    print(issubclass(obj,Foo))			# 检查第一个参数(对象)是否是第二个参数(类)的实例(包含父类),是True,不是False
    print(type(obj))					# 获取当前对象是由那个类创建。
  2. next and send

    def a():
        print('aaa')
        p = yield '123'     			# p1是send传过来的
        print('bbb')
    r = a()
    print(next(r))    					# next获得yield后面的值
    r.send('hello')						# send将值传入yield前面的变量
  3. 约束

    class BaseMessage(object):
        def send(self):
            """
            必须继承BaseMessage,然后其中必须编写send方法,用于完成具体业务逻辑。
            raise NotInplementedError(".send() 必须被重写。")
            """
            raise NotInplementedError(".send() 必须被重写。")
    # BaseMessage类用于约束,约束其派生类:保证派生类中必须编写send方法,不然执行可能就会报错。
    
    class BaseMessage(object):
        def send(self,x1):
            raise NotImplementedError(".send() 必须被重写。")
    class Email(BaseMessage):
        def send(self,x1):
            print("发送邮箱")
    obj = Email()
    obj.send(1)
  4. 总结

    1. 什么是接口以及作用?接口是一种数据类型,主要用于约束派生类中必须实现指定的方法,python中不存在,java和c# 中是存在的。

    2. python中使用过什么类约束呢?抽象类+抽象方法,编写上麻烦,人为主动抛出异常

    3. 约束时,抛出的异常是否可以用其他的?不专业:raise Exception(“.send() 必须被重写.”),专业:raise NotImplementedError(“.send() 必须被重写.”)

7.用三闲呀

7.1 error

  1. 自定义异常用于,各种异常。

    #知识点:如何自定义异常类?
    class MyException(Exception):
        def __init__(self,code,msg):
            self.code = code
            self.msg = msg
    try:
        #知识点:主动抛出异常
        raise MyException(1000,"操作异常")
        
    except KeyError as obj:    
        print(obj,1111)
    except MyException as obj: #知识点:捕获异常
        print(obj,2222)
    except Exception as obj:
        print(obj,3333)

7.2 日志

  1. 用的不多,了解即可。

    import logging
    
    logger = logging.basicConfig(filename="xxx.txt"
                        		fornat="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s",
                         		datefmt="%Y-%m-%d %H:%M:%S"
    				   		   level=30)
    
    logging.debug("x1") 		#10   	#测试
    logging.info("x2") 			#20     #正常
    logging.warning("x3") 		#30 	#警告
    logging.error("x4") 		#40    	#报错
    logging.critical("x5") 		#50 	#严重错误
    logging.log(10,"x6") 		#60   	#自定义日志
    
    #filename,"文件名或文件路径"fornat,datefmt"asctime时间 - name用户名 - levelname级别 - module当前文件名: %message文件内容"时间,level=级别
    
    
    import logging
    
    logger = logging.basicConfig(filename="xxx.txt"
                        		fornat="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s",
                         		datefmt="%Y-%m-%d %H:%M:%S"
    				   		   level=30)
    
    import traceback
    
    def func():
        try:
            a = a + 1
        except Exception as e:
            #获取当前错误的堆栈信息
            msg = traceback.format_exc()
            logging.error(msg)
    func()        
  2. 自定义日志

    import logging
    
    # 创建一个操作日志的对象logger(依赖FileHandler)
    file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')
    file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s"))
    
    logger1 = logging.Logger('s1', level=logging.ERROR)
    logger1.addHandler(file_handler)
    
    logger1.error('123123123')

7.3 正则

  1. 在实际开发中常用查找某些复杂规则的字符串的需要,这时候就可以使用正则表达式。通用性强。

  2. 匹配Regex对象

    import re 
    phoneNumRegex = re.compile(r"\d\d\d-\d\d\d-\d\d\d")			#创建一个Regex对象.
    mo = phoneNumRegex.search("My number is 145-126-187.")		#将Regex和要匹配的字符串进行匹配,匹配满足条件的第一个
    mo = phoneNumRegex.findall("My number is 145-126-187 or 568-874-589.")	#将Regex和要匹配的字符串进行匹配,匹配满足条件的所有返回list
    mo = phoneNumRegex.sub("000-000-000","My number is 145-126-187.")	#将Regex和要匹配的字符串进行匹配,匹配满足条件后进行替换
    print(mo.group())											#获取匹配的数据

     

  3. 正则表达式就是记录文本规则的代码,正则表达式需要用到re模块

    import re
    result = re.match(正则表达式,要匹配的字符串)					#使用match方法进行匹配
    result.group()												#提取数据,如果正则中分过组,可以加入数字参数获取每个小组.
  4. 单个字符匹配

    .    #匹配任意1个字符(除\n)
    []   #匹配[]中列举的字符
    \d   #匹配数字 0~1
    \D   #匹配非数字
    \s   #匹配空白
    \S   #匹配非空白
    \w   #匹配非特殊字符,a~z/A~Z/0~9/_/汉字
    \W   #匹配特殊字符
  5. 多个字符匹配

    *    #匹配前一个字符出现0或n次
    +    #匹配前一个字符出现1或n次
    ?    #匹配前一个字符出现0或1次
    {m}  #匹配前一个字符出现m次
    {m,n}#匹配前一个字符出现从m到n次
  6. 匹配开和尾

    ^    #匹配字符串开头
    $    #匹配字符串结尾
  7. 匹配分组

    |          #匹配左右任意一个表达式
    (ab)       #将括号中字符作为一个分组
    \num       #引用分组num匹配到的字符
    (?p<name>) #分组起别名
    (?P=name)  #引用别名为name分组匹配到的字符串

8.练习题呀

  1. 进度条

    #导入模块os
    import os
    #获取文件的总大小(字节)
    file_size = os.stat("asdlkfjsldjf.mp4").st_size
    
    # 2.一点一点的读取文件
    read_size = 0
    with open("asdlkfjsldjf.mp4",mode="rb") as f1:
        while read_size < file_size:
            chunk = f1.read(1024)
            #每次最多去读取1024字节
            read_size += len(chunk)
            val = int(read_size / file_size * 100)
            print("%s%%\r" %val,end="")
  2. 商品管理

    def goods():
        """
        商品管理
        :return:
        """
        func_dict = {"1":goods_list,"2":search_goods,"
    3":create_goods}
        while True:
         print("1,商品列表;2.模糊搜索,3.求人信息")
         num = input("请选择序号(N/n):")
         if num.upper() =="n":
            return
         func = func_dict.get(num)
         if not func:
             print("输入错误,请重新输入!")
             continue
         func()

高级阶段

1.基础知识

  1. 架构有:CS架构(Client/Server)、浏览器:BS架构(Broeser/Server)

  2. 如何实现相互通信,编写两个软件,软件之间相互通信、两个人直接连接 (网线)。

  3. TCP和UDP

  • TCP (Transmission Control Protocol)可靠的、面向连接的协议、传输效率低全双工通信、面向字节流。使用TCP的应用:web浏览器;电子邮件、文件传输程序。

  • UDP(User Datagram Prolocol)不可靠的,无连接的服务,传输效率高,一对一,一对多,多对一,多对多,面向报文,静最大努力服务,无堵塞控制。使用UDP的应用:域名系统(DNS);视频流;IP语音。

  1. 一个及其联网需要有一个ip、子网掩码、网关、DNS。

  2. 局域网内:广播、单播、广播风暴、arp协议

  3. 总结:

  4. 相互通信本质发送二进制,交换机用于连接局域网中的设备,通过ipconfig查看自己的内网IP

  5. DHCP,自动为局域网内容电脑分配ip;网关,路由器中连接交换机的口;ip 4个点分的十进制表示

  6. DNS

    • 域名:名称.一级.二级:端口\文件夹\文件.html

    • 问题来了,域名和ip的对应关系在哪里?

      • 本地:

        • win本地电脑:c:\windows\System32\drvers\etc\hosts(11.11.11.11 liyongqiang.com)

        • Linux/Mac电脑:/etc/hosts

      • DNS服务器:全球顶级DNS服务器13台:www.luffycity.com 47.95.64.113

  7. 网络基础

    • 端口,是什么?为什么要有?

      • 端口是为了将同一个电脑上的不同程序进行隔离。

      • 总范围1 – 65535,但是1 – 1024已经被系统程序占了。

  8. 国际标准化组织(ISO/OSI)

    • 7层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层

    • 5层:应用层(表示层/会话层)、传输层、网络层、数据链路层、物理层

    • 4层:应用层(应用层/表示层/会话层)、传输层、网络层、物理层(数据链路层/物理层)

  9. TCP三次握手/四次挥手

    • socket客户端向服务端发起连接请求:请求连接、允许连接、连接成功

    • 服务端和客户端端来连接:请求断开连接、正在整理数据、允许断开连接、程序断开完成

    • 补充:断开连接时,反应到代码上:抛出异常/发送空内容

  10. 操作系统/应用程序

    1. 硬件:硬盘、cpu、主板、显卡、内存、电源

    2. 装系统(软件),系统就是一个由程序员写出来软件,该软件用于控制计算机的硬件,让它们之间进行相互配合。

    3. 安软件(安装应用程序),qq、百度云、pycharm

  11. 并发和并行:并发,伪,由于执行速度特别快,人感觉不到迟钝;并行,真,创建10个人同时操作。

  12. 到底什么是线程?什么是进程?python之际没有,python中调用的操作系统的线程和进程。

    import threading
    print("666")
    
    def func(arg):
        print(arg)
    t = threading.Thread(target=func)
    t.start()
    print("end")
  13. 线程:工作的最小单元,共享进程中所有的资源,每个线程可以分担一些任务,最终完成最后和结果。

  14. 进程:独立开辟内存,进程之间的数据隔离

  15. 总结

    1. 程序员写好代码在操作系统上运行(依赖解释器)

    2. python多线程情况下:计算密集型操作:效率低。(GIL锁)、IO操作:效率高

    3. python多进程的情况下:计算密集型操作:效率高(浪费资源)、IO操作:效率高(浪费资源)

    4. 以后写python时:IO密集型用多线程,文件/输入输出/socket网络通信、计算密集型用多进程

    5. JAVA多线程情况下:计算密集型操作:效率高、IO操作:效率高

    6. python中线程和进程(GIL锁)GIL锁,全局解释器锁。用于限制一个进程中同一时刻只有一个线程被cpu调动。扩展:默认GIL锁在执行100个CPU指令(过期时间)

2.基本网络

2.1 socket

  1. 服务端

    import socket
    
    # 创建服务端socket对象
    server = socket.socket()
    # 绑定IP和端口
    server.bind(('192.168.13.155',8000))
    # 后边可以等5个人
    server.listen(5)
    print('服务端准备开始接收客户端的连接')
    # 等待客户端来连接,如果没人来就傻傻的等待。
    # conn是客户端和服务端连接的对象(伞),服务端以后要通过该对象进行收发数据。
    # addr是客户端的地址信息。
    # #### 阻塞,只有有客户端进行连接,则获取客户端连接然后开始进行通信。
    conn,addr = server.accept()
    print('已经有人连接上了,客户端信息:',conn,addr)
    
    # 通过对象去获取(王晓东通过伞给我发送的消息)
    # 1024表示:服务端通过(伞)获取数据时,一次性最多拿1024字节。
    data = conn.recv(1024)
    print('已经有人发来消息了',data)
    
    # 服务端通过连接对象(伞)给客户端回复了一个消息。
    conn.send(b'stop')
    # 与客户端断开连接(放开那把伞)
    conn.close()
    # 关闭服务端的服务
    server.close()
  2. 客户端

    import socket
    
    client = socket.socket()
    
    #王晓东向服务端发起连接请求(递伞)
    #堵塞,去连接,直到连接成功后才会继续向下走。
    client.connect(("xx.xx.xx.xx",8000))
    
    #连接上服务端后,向服务端发送消息
    client.send(b"hello")
    #万晓东等待服务端给它发送消息
    data = client.recv(1024)
    print(data)
    #关闭自己
    client.close()
  3. 基于socket模块实现网络通信

  4. 为什么要网络通信发送的是字节?而不是字符串?py2,send/recv 都是字节、py3,send/recv 都是字符串。

  5. 服务端:accept,阻塞:等待客户端来连接、recv,阻塞:等待客户端发来数据。

  6. 客户端:connect,阻塞:一直在连接,值到连接成功才往下运行其他代码、recv,阻塞:等待服务器发来数据。

2.2 subprocess/struct

  1. 标准输入

    import subprocess
    
    res=subprocess.Popen("dir",#指定命令名
                          shell=True,
                          stderr=subprocess.PIPE,
                          #错误输出
                          stdout=subprocess.PIPE,)
                          #接收系统返回的值
    print(res.stdout.read().decode("gbk"))
    #输出接收到的值以“gbk”
  2. 包判定计算大小

    import struct 
    #i模式把123456压缩,四个字节,如果大于就报错
    # 最大是2的31次方减一
    header_pack=struct.pack("i",2147483647)#压包
    print(header_pack)
    obj = struct.unpack("i",beader_pack)#解包
    print(obj)

2.3 socketserver

  1. 快速server模块

    import socketserver
    
    #所有的网络通信都在这里面执行
    class Myserver(socketserver.BaseRequestHandler):
    	def handle(self):    
            whlie True:
                try:
                    print("等待")
                    #之前的conn现在是self.request
                    data = self.request.recv(1024)
                    if data == b"t"
                        break
                    response = data + b"sb"
                    self.request.send(response)
                except Exception as e:
                    break
            self.request.close()
    #创建服务端加ip,端口,类名
    #1.创建socket对象 2.self.socket.bind() 3.self.socket.listen(5)
    server = socketserver.ThreadingTCPServer(("127.0.0.1",8899),Myserver)
    #等待连接连接成功后会从类开始执行
    server.serve_forever()

3.用三程呀

3.1 线程

  1. 使用threading实现

    import threading
    import time
    
    def func(arg):
        #获取当前执行该函数的线程的对象
        t = thredding.current_thread()
        #根据当前线程对象获取当前线程名称
        name = t.getName()
        time.sleep(2)
        print(name,arg)
        
    t1 = threading.Thread(target=func,args=(3,))
    #为True就让主进程不等待直接执行完
    #为False就让主进程等待子进程,默认时等待的
    t1.setDaemon(True)
    #设置名
    t1.setName("哇哈哈")
    t1.start
    #无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。
    #有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。
    t1.join(2)
  2. 自定义创建多线程

    import socket
    import threading
    
    def task(conn):
        data = conn.recv(1024)
        print(data)
        conn.close()
    
    server = socket.socket()
    server.bind(("127.0.0.1,8822"))
    server.listen(5)
    
    while True:
        conn,addr = server.accept()
        t = threading.Thread(target=task,args=(conn,))
        t.start()
  3. 面向对象多线程

    import therading
    #1
    def func(arg):
        print(arg)
    t1 = threading.Thread(target=func,args=(11,))
    t1.start
    #2
    class MyThread(threading.Thread):
        def run(self):
        	print(1111,self._args,self._kwargs)
    t1 = MyThread(args=(11,))
    t1.start()
    t2 = MyThread(args=(22,))
    t2.start()
  4. uuid模块

    import uuid
    随机生成字符串
    v = str(uuid.uuid4())
    print(v)
  5. requests模块

    #需要下载 pip install requests
    #爬图片
    import reqquest
    import uuid
    import threading
    
    url_list = []
    def task(url):
        """
        1.DNS解析,根据域名解析出ip
        2.创建socket客户端    sk = socket.socket()
        3.向服务端发起连接请求 sk.connect()
        4.发起数据(我要图片) sk.send(...)
        5.接收数据			 sk.recv(8096)
        """
        #帮你创建连接然后域名解析,然后然他给你发图片
        ret = requests.get(url)
        #请求下载下来的图片
        file_name = str(uuid.uuid4()) + ".jpg"
        with open(file_name,mode="wb")as f:
            f.write(ret.content)
            
    for url in url_list:
        t = threading.Thread(target=task,args=(url,))
        t.start()
  6. 锁的初步认识

    import time
    import threading
    
    lock = threading.RLock()
    
    n = 10
    
    def task(i):
        print("这段代码不加锁")
        lock.acquire()#加锁
        global n
        print("当前线程",i,"读取到的n值为:",n)
        n = i
        time.sleep(1)
        print("当前线程",i,"修改n值为:",n)
        lock.release()#解锁
        
    for i in range(10):
        t = threading.Thread(target=task,args=(i,))
    t.start()
  7. 总结

    1. 应用程序/进程/线程的关系?

    2. 为什么要创建线程?由于线程时cpu工作的最小单元,创建线程可以利用多核优势实现并行操作(JAVA/C#)

    3. 为什么要创建进程?进程和进程之间做数据隔离(Java/c#)

    4. python

      1. python中存在一个GIL锁,造成:多线程无法利用多核优势、解决:开多进程处理(浪费资源)

      2. 线程的创建:Thread、MyTread

      3. 其他:join、setDeanon、setName、threading.current_thread()

      4. 锁,获得、释放

    5. python的GIL锁

      • python内置的一个全局解释器锁,锁的作用就是保证同一刻一个进程中只有一个线程可以被cpu调用。

      • 为什么有这把GIL锁?python语言的创始人在开发这门语言时,目的快速把语言开发出来,如果加上GIL锁(c语言加锁)

    6. 进程和线程的区别?线程,cpu工作的最小单元。、进程,线程提供一个资源共享的空间、一个进程中默认是有一个主线程。

    7. 进程和线程的使用准则:计算密集型:多进程、IO密集型:多线程

    8. 线程创建的越多越好吗?不好,线程之间切换时,要做上下文管理。

1.线程池

  1. 基本使用

    from concurrent.futures import ThreadPoolExecutor
    import time
    
    def task(a1,a2):
        time.sleep(2)
        print(a1,a2)
        
    #创建了一个线程池(最多5个线程)
    pool = ThreadPoolExecutor(5)
    
    for i in range(40):
        #去线程池中申请一个线程,让线程执行task函数
        pool.submit(task,i,8)
  2. 生产者和消费者模型

    # by luffycity.com
    import time
    import queue
    import threading
    q = queue.Queue() # 线程安全
    
    def producer(id):
        """
        生产者
        :return:
        """
        while True:
            time.sleep(2)
            q.put('包子')			# 存值
            print('厨师%s 生产了一个包子' %id )
    
    for i in range(1,4):
        t = threading.Thread(target=producer,args=(i,))
        t.start()
    
    def consumer(id):
        """
        消费者
        :return:
        """
        while True:
            time.sleep(1)
            v1 = q.get()		# 取值
            print('顾客 %s 吃了一个包子' % id)
    
    for i in range(1,3):
        t = threading.Thread(target=consumer,args=(i,))
        t.start()
  3. 生产者消费者模型解决了什么问题?不用一直等待的问题。

2.独立空间

  1. 作用:内部自动为每个线程维护一个空间(字典),用于当前存储属于自己的值。保证线程之间的数据隔离。

  2. 基本使用

    import time
    import threading
    
    v = threading.local()
    
    def func(arg):
        #内部会为当前线程创建一个空间用于储存:phone=自己的值
        v.phone = arg
        time.sleep(2)
        print(v.phone,arg)#去当前线程自己空间获值
        
    for i in range(10):
        t = threading.Thread(target=func,args=(i,))
        t.start()
  3. local原理

    import time
    import threading
    
    def func(arg):
        ident = threading.get_ident()
        DATA_DICT[ident] = arg
        time.sleep(2)
        print(DATA_DICT[ident],arg)
        
    for i in range(10):
        t = threading.Thread(target=func,args=(i,))
        t.start()
  4. 实例

    # by luffycity.com
    """
    以后:Flask框架内部看到源码 上下文管理
    
    """
    import time
    import threading
    INFO = {}
    class Local(object):
    
        def __getattr__(self, item):
            ident = threading.get_ident()
            return INFO[ident][item]
    
        def __setattr__(self, key, value):
            ident = threading.get_ident()
            if ident in INFO:
                INFO[ident][key] = value
            else:
                INFO[ident] = {key:value}
    
    obj = Local()
    
    def func(arg):
        obj.phone = arg # 调用对象的 __setattr__方法(“phone”,1)
        time.sleep(2)
        print(obj.phone,arg)
    
    
    for i in range(10):
        t =threading.Thread(target=func,args=(i,))
        t.start()

3.2 进程

  1. 基本使用

    #mac系统不会报错#win系统会报错
    
    def task(arg):
        print(arg)
    for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.start()
    #这样win系统就不会报错了
    def task(arg):
        print(arg)
    
    if __name__ =="__main__":
        for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.start()
  2. 不共享

    import multiprocssing
    import threading
    import queue
    data_list = []
    def task(arg):
        data_list.append(arg)
        print(data_list)
        
    def run():
        for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.start()
    
    if __name__ =="__main__":
        run()
  3. 进程常用功能

    import multiprocssing
    import threading
    import queue
    
    def task(arg):
        time.sleep(2)
        print(arg)
        
    def run():
        for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.start()
    	p.join()#等待进程
    
    if __name__ =="__main__":
        run()
        
    ###########################
    def task(arg):
        time.sleep(2)
        print(arg)
        
    def run():
        for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.daemon = False#True不等子进程,相反
        p.start()
    
    if __name__ =="__main__":
        run()
    ###################
    def task(arg):
        #获取当前进程
        p = multiprocessing.current_process()
    	print(p.name)
        time.sleep(2)
        print(arg)
        
    def run():
        for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.name = "pp1"#给进程命名
        p.start()
    
    if __name__ =="__main__":
        run()
    #########################
    def task(arg):
        #获取当前进程
        p = multiprocessing.current_process()
    	print(p.ident)#打印当前进程
        time.sleep(2)
        print(arg)
        
    def run():
        for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.name = "pp1"#给进程命名
        p.start()
    
    if __name__ =="__main__":
        run()
  4. 面向对象创建进程

    import multiprocssing
    import threading
    import queue
    
    class MyProcess(multiprocessing.Process):    
        def task(arg):
            def run(self):
                print("当前进程",multiprocessing.current_process())
    
    def run():
        p.MyProcess()
        p.start()
    
    if __name__ =="__main__":
        run()
  5. 进程间的数据共享:先进先出 队列、先进后出 站,进程间的共享

    #linux这样写
    import multiprocessing
    q = multiprocessing.Queue()
    def task(arg,q):
        q.put(arg)
        
    def run():
        for i in range(10):
            p = multiprocessing.Process(target=task,args=(i,q,))
    while True:
        v = q.get()
        print(v)
    
    if __name__ == "__main__"
    	run()
        
    ############################
    #windows这样写
    import multiprocessing
    
    def task(arg,q):
        q.put(arg)
        
    if __name__ == "__main__"
    	q = multiprocessing.Queue()
        for i in range(10):
            p = multiprocessing.Process(target=task,args=(i,q,))
    while True:
        v = q.get()
        print(v)
  6. 进程间的共享 Manager

    #linux这样写
    import multiprocessing
    q = multiprocessing.Manager()
    dic = m.dict()
    def task(arg,q):
        dic[arg] = 100
        
    def run():
        for i in range(10):
            p = multiprocessing.Process(target=task,args=(i,q,))
            p.start()
            
        input(">>>")
        print(dic.values())
    if __name__ == "__main__"
    	run()
    ############################
    #windows这样写
    import multiprocessing
    
    def task(arg,q):
        dic[arg] = 100
        
    if __name__ == "__main__"
    	m = multiprocessing.Manager()
        for i in range(10):
            p = multiprocessing.Process(target=task,args=(i,m,))
            p.join()
        print(dic)
        
    ######################2
    import multiprocessing
    
    def task(arg,q):
        dic[arg] = 100
        
    if __name__ == "__main__"
    	m = multiprocessing.Manager()
        dic = m.dict()
        process_list[]
        for i in range(10):
            p = multiprocessing.Process(target=task,args=(i,cic))
            p.start()
            
            process_list.append(p)
        while True:
            count = 0
            for p in process_list:
                if not p.is_alive():#True是还在执行,Fasle是已执行完
                    cunt +=1
                if count == len(process_list):
                    break
            print(dic)
  7. 进程锁

    import time
    import multiprocessing
    
    lock = multiprocessing.RLock()
    
    def task(arg):
        print("鬼子来了")
        lock.acquire()
        time.sleep(2)
        print(arg)
        lock.release()
        
    if __name__ == "__main__":
        p1 = multiprocessing.Process(target=task,args=1)
        p1.start()
        
        p2 = multiprocessing.Process(target=task,args=1)
        p2.start()

1.进程池

  1. 基本使用

    import time
    from comcurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    # #############################线程池
    def task (arg):
        time.sleep(2)
        print(arg)
        
    if __name__ == "__main__":
        pool = ThreadPoolExecutor(5)
        for i in range(10):
            pool.submit(task,i)
    # #############################进程池
    def task (arg):
        time.sleep(2)
        print(arg)
        
    if __name__ == "__main__":
        pool = ProcessPoolExecutor(5)
        for i in range(10):
            pool.submit(task,i)        

3.3 协程

  1. 进程线程,操作系统中存在

  2. 协程,是有程序员创造出来的一个不是真实存在的东西;是微线程,对一个线程进程分片,是的线程在代码块之间进行来回切换执行,而不是在原来逐行执行。

    pip install gevent
    pip install greenlet
    import greenlet
    
    def f1():
        print(11)
        #跳到f2执行f2函数
        gr2.switch()
        print(22)
    def f2():
        print(33)
        #跳到f1执行f1函数
        gr1.switch()
        print(44)
        
    #协程 gr1
    gr1 = greenlet.greenlet(f1)
    gr2 = greenlet.greenlet(f2)
    gr1.switch()
  3. IO多路复用+协程

    from gevent import monkey
    monkey.patch_all()#以后代码中遇到IO都会自动执行greenlet的switch进行切换
    import requests
    import gevent
    
    def get_page(url):
        ret = requests.get(url)
        print(url,ret.content)
        
    gevent.joinall([gevent.spawn(get_page,"https://www.python.org/")]) #一个协程
  4. 总结

    1. 什么是协程?协程也可以成为微线程,就是开发者控制线程执行流程,控制先执行某段代码然后切换到另外执行代码。

    2. 协程可以调高并发吗?执行自己本身无法实现并发,协程+IO切换性能提高。

    3. 进程、线程、协程,协程+IO切换:基于事件循环的异步非阻塞框架:Twisted、手动实现协程:yield关键字生成器

      def f1():
          print(11)
          #第一次执行到这卡住再将1赋给send
          x1 = yield 1
          #接收v1.send(999)的值赋给x1
          print(x1,22)
          #返回一个二
          yield 2
          print(33)
          
      def f2():
          print(44)
          yield
          print(55)
          yield
          print(66)
      
      #第一次执行接受yield返回的值赋给ret
      ret = v1.send(None)
      pritn(v1)
      #发送一个值,接受一个值
      v = v1.send(999)

4.快用锁呀

  1. 线程安全,多线程操作时,内部会让所有线程排队处理。如:list/dict/Queue

  2. 需求,创建100个线程:锁,把自己的添加到列表中,在读取列表的最后一个;解锁。

1 lock

  1. 基本使用

    import threading
    import time
    
    v = []
    #创建锁
    lock = threading.Lock()
    
    def func(arg):
        #上锁
        lock.acquire()
        v.append(arg)
        time.sleep(0.01)
        m = v[-1]
        print(arg,m)
        #解锁
        lock.release()
        
    for i in range(10):
        t = treading.Thread(target=func,args=(i,))
        t.start()

2 RLock

  1. 基本使用

    import threading
    import time
    
    v = []
    #创建锁
    lock = threading.RLock()
    
    def func(arg):
        #上锁
        lock.acquire()
        v.append(arg)
        time.sleep(0.01)
        m = v[-1]
        print(arg,m)
        #解锁
        lock.release()
        
    for i in range(10):
        t = treading.Thread(target=func,args=(i,))
        t.start()

3 信号量

  1. 基本使用

    import threading
    import time
    
    v = []
    #创建锁
    lock = threading.Lock()
    #一次执行多个
    lock = threading.BoundedSemaphore(3)
    def func(arg):
        #上锁
        lock.acquire()
        v.append(arg)
        time.sleep(0.01)
        m = v[-1]
        print(arg,m)
        #解锁
        lock.release()
        
    for i in range(10):
        t = treading.Thread(target=func,args=(i,))
        t.start()

4 Condition

  1. 基本使用

    import threading
    import time
    
    v = []
    #创建锁
    lock = threading.Condition()
    #一次执行多个
    lock = threading.BoundedSemaphore(3)
    def func(arg):
        #上锁
        lock.acquire()
        v.append(arg)
        time.sleep(0.01)
        m = v[-1]
        print(arg,m)
        
    for i in range(10):
        t = treading.Thread(target=func,args=(i,))
        t.start()
        
    while True:
        inp = int(input(">>>"))
        lock.release()    #解锁
        lock.release()
        
    ##########################2 
    #一次执行多个
    def xxx():
        print("111")
        input(">>>")
        return True
    
    def func(arg):
        print("222")
       lok.wait_for(xxx)#锁住了,只有条件为True,才往下走1,一个
        print(arg)
        time.sleep(1)
        
    for i in range(10):
        t = treading.Thread(target=func,args=(i,))
        t.start()

5 Event

  1. 基本使用

    import time
    import threading
    
    lock = threading.Event()
    
    def func(arg):
        print('线程来了')
        lock.wait() # 加锁:红灯
        print(arg)
    
    for i in range(10):
        t =threading.Thread(target=func,args=(i,))
        t.start()
    
    input(">>>>")
    lock.set() # 绿灯
    
    lock.clear() # 再次变红灯
    
    for i in range(10):
        t =threading.Thread(target=func,args=(i,))
        t.start()
    
    input(">>>>")
    lock.set()

4.发送请求

  1. 基本使用

    import socket
    import sequests
    
    #方式一
    ret = requests.get("https://www.baidu.com/s?wd=alex")
    
    #方式二
    cloent = socket.socket()
    #和百度创建连接:阻塞
    client.connect(("www.baidu.com",80))
    #问百度你要什么?
    client.sendall(b"GET /s?wd=alex http/1.1\r\nhost:www.baidu.com\r\n\r\n")
    #我等着百度给我的回复
    chunk_list = []
    while True:
    	chunk = client.recv(1024)
        if not chunk:
            break
        chunk_list.append(chunk)
        
    body = b"".join(chunk_list)
    print(body.decode("utf-8"))

5.非阻塞呀

  1. 基本使用

    import socket
    
    #方式二
    cloent = socket.socket()
    cloent.setblocking(False)#将原来阻塞的变成非阻塞
    #和百度创建连接:阻塞
    try:
    	client.connect(("www.baidu.com",80))
    #问百度你要什么?
    except BlockingIOError as e:
        pass
    client.sendall(b"GET /s?wd=alex http/1.1\r\nhost:www.baidu.com\r\n\r\n")
    #我等着百度给我的回复
    chunk_list = []
    while True:
    	chunk = client.recv(1024)#将原来阻塞的变成非阻塞
        if not chunk:
            break
        chunk_list.append(chunk)
        
    body = b"".join(chunk_list)
    print(body.decode("utf-8"))
    ###########################################
    #单线程的并发
    import socket
    import select
    #方式二
    cloent = socket.socket()
    cloent.setblocking(False)#将原来阻塞的变成非阻塞
    #和百度创建连接:阻塞
    try:
    	client.connect(("www.baidu.com",80))
    #问百度你要什么?
    except BlockingIOError as e:
        pass
    socket_list = [client1,client2,client3]
    conn_list = [client1,client2,client3]
    while True:
        rlist,wlist,elist = select.select(socket_list,conn_list,[],0.005)
        #如果有数据返回就把他放到rlist,如果有连接成功就把他放到wlist,如果有异常就把他放到[]中
        #socket_list是检测是否服务端给我返回数据了    可读
        #conn_list检测其中的所有socket是否已经和服务端连接成功    可写
        #[]获取异常
        #0.005是最多等0.005秒
        for sk in wlist:
            if sk == client1:
                sk.sendall(b"GET /s?wd=alex http/1.1\r\nhost:www.baidu.com\r\n\r\n")
            else:
                sk.sendall(b"GET /s?wd=alex http/1.1\r\nhost:www.baidu.com\r\n\r\n")
                
        for sk in rlist:
            chunk_list = []
            while True:
                try:
                    chunk = sk.recv(8096)
                    if not chunk:
                        break
                    chunk_list.append(chunk)
                except BlockingIOError as e:
                    break
            body = b"".join(chunk_list)
            print(body.decode("utf-8"))
            sk.close()
            socket_list.remove(sk)
        if not socket_list:
            break
  2. IO多路复用作用:检测多个socket是否已经发生变化(是否已经连接完成/是否已经获取数据)(可读/可写)

  3. IO多路复用,socket的会堵塞、Twisted ,基于事件循环实现的异步非堵塞框架,异步:执行完某个人物后自动调用我给他的函数。

    #单线程的并发
    import socket
    import select
    #方式二
    cloent = socket.socket()
    cloent.setblocking(False)#将原来阻塞的变成非阻塞
    #和百度创建连接:阻塞
    try:
    	client.connect(("www.baidu.com",80))
    #问百度你要什么?
    except BlockingIOError as e:
        pass
    class Foo(object):
        def __init__(self,sk):
            self.sk = sk
        def fileno(self):
            return self.sk.fileno()
    """
    1.select.select(socket_list,conn_list,[],0.005)
    	select监听的socket_list/conn_list内部会调用列表中每一个值的fileno方法,获取该返回值并去系统中检测。
    	
    2.方式一:
    	select.select([client1,])
    """    
    socket_list = [Foo(client1),Foo(client2),Foo(client3)]
    conn_list = [client1,client2,client3]
    while True:
        rlist,wlist,elist = select.select(socket_list,conn_list,[],0.005)
        #如果有数据返回就把他放到rlist,如果有连接成功就把他放到wlist,如果有异常就把他放到[]中
        #socket_list是检测是否服务端给我返回数据了    可读
        #conn_list检测其中的所有socket是否已经和服务端连接成功    可写
        #[]获取异常
        #0.005是最多等0.005秒
        for sk in wlist:
            if sk == client1:
                sk.sendall(b"GET /s?wd=alex http/1.1\r\nhost:www.baidu.com\r\n\r\n")
            else:
                sk.sendall(b"GET /s?wd=alex http/1.1\r\nhost:www.baidu.com\r\n\r\n")
                
        for sk in rlist:
            chunk_list = []
            while True:
                try:
                    chunk = sk.recv(8096)
                    if not chunk:
                        break
                    chunk_list.append(chunk)
                except BlockingIOError as e:
                    break
            body = b"".join(chunk_list)
            print(body.decode("utf-8"))
            sk.close()
            socket_list.remove(sk)
        if not socket_list:
            break 
  4. 实现非阻塞

    import socket
    import select
    
    class Req(object):
        def __init__(self,sk,func):
            self.sock = sk
            self.func = func
    
        def fileno(self):
            return self.sock.fileno()
    
    
    class Nb(object):
    
        def __init__(self):
            self.conn_list = []
            self.socket_list = []
    
        def add(self,url,func):
            client = socket.socket()
            client.setblocking(False)  # 非阻塞
            try:
                client.connect((url, 80))
            except BlockingIOError as e:
                pass
            obj = Req(client,func)
            self.conn_list.append(obj)
            self.socket_list.append(obj)
    
        def run(self):
    
            while True:
                rlist,wlist,elist = select.select(self.socket_list,self.conn_list,[],0.005)
                # wlist中表示已经连接成功的req对象
                for sk in wlist:
                    # 发生变换的req对象
                    sk.sock.sendall(b'GET /s?wd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n')
                    self.conn_list.remove(sk)
                for sk in rlist:
                    chunk_list = []
                    while True:
                        try:
                            chunk = sk.sock.recv(8096)
                            if not chunk:
                                break
                            chunk_list.append(chunk)
                        except BlockingIOError as e:
                            break
                    body = b''.join(chunk_list)
                    # print(body.decode('utf-8'))
                    sk.func(body)
                    sk.sock.close()
                    self.socket_list.remove(sk)
                if not self.socket_list:
                    break
    
    
    def baidu_repsonse(body):
        print('百度下载结果:',body)
    
    def sogou_repsonse(body):
        print('搜狗下载结果:', body)
    
    def oldboyedu_repsonse(body):
        print('老男孩下载结果:', body)
    
    
    t1 = Nb()
    t1.add('www.baidu.com',baidu_repsonse)
    t1.add('www.sogou.com',sogou_repsonse)
    t1.add('www.oldboyedu.com',oldboyedu_repsonse)
    t1.run()
  5. 总结

    1. socket默认是否阻塞的?阻塞体现在哪里?

    2. 如何让socket编程非阻塞?

    3. IO多路复用作用?

      • 检测多个socket是否发生变化。

      • 操作系统检测socket是否发生变化,有三种模式:

        • select:做多1024个socket;循环去检测。

        • poll:不限制监听socket个数;循环去检测(水平触发)。

        • epoll:不限制监听socket个数;回调方式(边缘触发)。

      • python模块:select.select、select.epoll

    4. 提高并发方案:多进程、多线程、异步非堵塞模块(Twisted)scrapy框架(单线程完成并发)

9.练习题呀

  1. 解释器和编译器的区别?编译型先把代码编译成机器码 , 计算机寄存器去运行、解释型边解释边执行。

  2. py2/py3

    • 打印,py2中print ” xx”、py3中print(123)

    • 继承,py2中经典类/新式类、py3中新式类

    • 编码,py2中ascii可以修改#- * – encoding:utf-8 – * –、py3中utf-8可以修改#- * – encoding:utf-8 – * –

    • 字符串,py2中unicode v = u”root” 本质上用ynicode存储、(str/bytes) v = “root” 本质用字节存储、py3中str v = “root” 本质上用ynicode存储、bytes v = b”root” 本质用字节存储

    • 输入,py2中v1 = raw_input(“>>>”)、py3中v1 = input(“>>>”)

    • 范围,py2中range/xrange、py3中range

  3. 练习

    # Client
    import socket
    import struct
    sk = socket.socket()
    
    sk.connect(('127.0.0.1',8008))
    
    while 1:
        cmd = input("请输入命令:")
        sk.send(cmd.encode('utf-8')) # 字节
        if cmd=="":
            continue
        if cmd == 'exit':
            break
    
        # header_pack=sk.recv(4)
        # data_length=struct.unpack("i",header_pack)[0]
        # print("data_length",data_length)
        '''
        b'xxx/xxx/xxx/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
        
        
        '''
        data_length=int(sk.recv(1024).decode("utf8"))
        print("data_length",data_length)
    
        recv_data_length=0
        recv_data=b""
    
        while recv_data_length<data_length:
            data=sk.recv(1024)
            recv_data_length+=len(data)
            recv_data+=data
    
        print(recv_data.decode("gbk"))
    
    sk.close()
    
    # Server
    # by luffycity.com
    
    import socket
    import subprocess
    
    server = socket.socket()
    server.bind(('127.0.0.1',8008))
    server.listen(5)
    
    while True:
        print("server is working.....")
        conn,addr = server.accept()
        # 字节类型
        while True:
            # 针对window系统
            try:
                cmd = conn.recv(1024).decode("utf8") # 阻塞
    
                if cmd == b'exit':
                    break
    
                res=subprocess.Popen(cmd,
                                 shell=True,
                                 stderr=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 )
                # print("stdout",res.stdout.read())
                # print("stderr",res.stderr.read().decode("gbk"))
                out=res.stdout.read()
                err=res.stderr.read()
    
                print("out响应长度",len(out))
                print("err响应长度",len(err))
                if err:
                     import struct
                     header_pack = struct.pack("i", len(err))
                     conn.send(header_pack)
                     conn.send(err)
                else:
                     #构建报头
                     import struct
                     header_pack=struct.pack("i",len(out))
                     print("header_pack",header_pack)
                     # # 发送报头
                     conn.send(str(len(out)).encode("utf8"))
                     # 发送数据
                     conn.send(out)
            except Exception as e:
                break
        conn.close()
  4. 练习

    # Server
    
    import struct
    import socket
    import json
    import hashlib
    
    sock=socket.socket()
    sock.bind(('127.0.0.1',8800))
    sock.listen(5)
    
    while 1:
        print("server is working....")
        conn,addr= sock.accept()
        while 1:
    
            # 接收json的打包长度
            file_info_length_pack=conn.recv(4)
            file_info_length=struct.unpack("i",file_info_length_pack)[0]
    
            # 接收json字符串
            file_info_json=conn.recv(file_info_length).decode("utf8")
            file_info=json.loads(file_info_json)
    
            action=file_info.get("action")
            filename=file_info.get("filename")
            filesize=file_info.get("filesize")
    
            # 循环接收文件
            md5=hashlib.md5()
            with open("put/"+filename,"wb") as f:
                recv_data_length=0
                while recv_data_length<filesize:
                    data=conn.recv(1024)
                    recv_data_length+=len(data)
                    f.write(data)
                    # MD5摘要
                    md5.update(data)
                    print("文件总大小:%s,已成功接收%s"%(filesize,recv_data_length))
    
            print("接收成功!")
            conn.send(b"OK")
            print(md5.hexdigest())
            md5_val=md5.hexdigest()
            client_md5=conn.recv(1024).decode("utf8")
            if md5_val==client_md5:
                 conn.send(b"203")
            else:
                 conn.send(b"204")
                    
    # Client
    
    import socket
    import os
    import json
    import struct
    import hashlib
    
    sock=socket.socket()
    sock.connect(("127.0.0.1",8800))
    
    
    while 1 :
        cmd=input("请输入命令:") # put 111.jpg
    
        action,filename=cmd.strip().split(" ")
        filesize=os.path.getsize(filename)
    
        file_info={
            "action": action,
            "filename": filename,
            "filesize": filesize,
        }
        file_info_json=json.dumps(file_info).encode("utf8")
    
        ret=struct.pack("i",len(file_info_json))
        # 发送 file_info_json的打包长度
        sock.send(ret)
        # 发送 file_info_json字节串
        sock.send(file_info_json)
        # 发送 文件数据
        md5=hashlib.md5()
        with open(filename,"rb") as f:
            for line in f:
                sock.send(line)
                md5.update(line)
    
        data=sock.recv(1024)
        print(md5.hexdigest())
        md5_val=md5.hexdigest()
        sock.send(md5_val.encode("utf8"))
        is_valid=sock.recv(1024).decode('utf8')
        if is_valid=="203":
            print("文件完整!")
        else:
            print("文件上传失败!")
  5. 进度条

    import time
    
    def func(size,total_size):
        val = int(size/total_size * 100)
        time.sleep(0.2)
        print("\r%s%%|%" %(val,"*"*val,),end="")
    
    for i in range(100):
        func(i,100)
  6. 读取文件大小

    import os
    
    size = os.stat(r"sadf\asdf\d\").st_size
    print(size)
版权声明:本文为無敗の草原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/InvincibleGrass/p/17002819.html