Python.学习笔记.md

2019年12月04日 阅读数:94
这篇文章主要向大家介绍Python.学习笔记.md,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

1、Python学习笔记

1. 第一章 计算机基础

1-1. 1.1 硬件

计算机基本的硬件由:CPU / 内存 / 主板 / 硬盘 / 网卡 / 显卡 等组成,只有硬件但硬件之间没法进行交流和通讯。html

1-2. 1.2 操做系统

操做系统用于协同或控制硬件之间进行工做,常见的操做系统有那些:前端

  • windows
    • win xp
    • win7
    • win10
    • Windows sever
  • linux
    • centos 【公司线上通常用】
    • Redhat 企业级
    • Ubuntu 适合我的开发,图形化好
  • mac

1-3. 1.3 解释器或编译器

编程语言的开发者写的一个工具,将用户写的代码转换成010101交给操做系统去执行。java

1-3-1. 1.3.1 解释和编译型语言

解释型语言就相似于: 实时翻译,表明:Python / PHP / Ruby / Perlpython

编译型语言相似于:说完以后,总体再进行翻译,表明:C / C++ / Java / Go ...linux

1-4. 1.4 软件(应用程序)

软件又称为应用程序,就是咱们在电脑上使用的工具,相似于:记事本 / 图片查看 / 游戏git

1-5. 1.5 进制

对于计算机而言不管是文件存储 / 网络传输输入本质上都是:二进制(010101010101),如:电脑上存储视频/图片/文件都是二进制; QQ/微信聊天发送的表情/文字/语言/视频 也所有都是二进制。面试

进制:正则表达式

  • 2进制,计算机内部。
  • 8进制, 逢8进1
  • 10进制,人来进行使用通常状况下计算机能够获取10进制,而后再内部会自动转换成二进制并操做。
  • 16进制,通常用于表示二进制(用更短的内容表示更多的数据),一版是:\x 开头。10-15:ABCDEF

1-6. 1.6 单位换算

1TB=1024GB 1GB=1024MB 1MB=1024KB 1KB=1024B 1B=8bredis

2. 第二章 Python入门

2-1. 2.1 环境的安装

  • 解释器:py2 / py3 (环境变量)算法

    • python 2.7.16(2020官方再也不维护)
    • python 3.6.8(推荐,不用最新版本)

    最好安装在根目录下,若是同时安装2.7版本,更改解释器exe名字并作区分

    Linux解释器路径 #!/usr/bin/env python

  • 开发工具:pycharm

    • ctrl+?能够快速注释多行pycharm

    • Ctrl+D快速复制能够快速复制上一行

2-2. 2.2 编码

2-2-1. 2.2.1 编码基础

编码 简介
ASCII 英文及符号,8bit表示一内容,2**8=1byte
Unicode 万国码,32bit表示一内容,2**32=4byte
UTF-8 压缩的Unicode,8bit为一单位,省去高位0. 中文:3byte=24bit
GBK 支持简体中文和繁体中文,中文是2字节
GB2312 简体中文

2-2-2. 2.2.2 python编码相关

对于Python默认解释器编码:

  • py2: ascii
  • py3: utf-8

若是想要修改默认编码,则可使用:

# -*- coding:utf-8 -*- 

注意:对于操做文件时,要按照:以什么编写写入,就要用什么编码去打开。

2-3. 2.3 变量

2-3-1. 2.3.1 变量的做用

为某个值建立一个“外号”,之后在使用时候经过此外号就能够直接调用。

2-3-2. 2.3.2变量命名要求

  1. 变量名只能包含:字母/数字/下划线

  2. 数字不能开头

  3. 不能是python的关键字。

    [‘and’, ‘as’, ‘assert’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’,‘except’, ‘exec’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’,‘lambda’, ‘not’, ‘or’, ‘pass’, ‘print’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’,‘yield’]

  4. 建议:

    1. 见名知意: name = "alex" age= 18

    2. 用下划线链接:alex_dad = "吴佩其"

    3. 补充:AlexDad = '吴佩其' (驼峰式命名)

      # 建议变量名不要用:str/int/list/tuple/set/dict/float
      # user_list = [11,22,33] # 推荐
      # list = [11,22,33] # 不推荐
      # list = 'alex'
      # v = (11,22,33)
      # v1 = list(v)

2-4. 2.4 注释

  • 单行注释 #注释
  • 多行注释 """注释"""
  • 文件注释 文件开头"""内容"""

2-5. 2.5 输入输出

2-5-1. 2.5.1 语法格式

差异对比 输入 输出
python2 raw_input("输入") print "输出"
python3 input("输入") print("输出")

注意:input()获取的数据类型为字符串

2-5-2. 2.5.2 格式化输出

  • %s: 字符串占位符

    # 字符串格式化存在的意义
    name = input('姓名:')
    do = input('在干什么:')
    template = "%s在教室,%s。" %(name,do,)    #最后加逗号
    print(template)
    # 直接作占位符
    # template = "我是%s,年龄%s, 职业%s。" %("alex",73,'讲鸡汤',)
    # print(template)
  • %d: 整形站位符

    # template = "我是%s,年龄%d, 职业%s。" %("alex",73,'讲鸡汤',)
    # print(template)
  • %%: 输出%

    # name = 'alex'
    # template = "%s如今手机的电量是100%%" %(name,)
    # print(template)
  • 练习

    name = input('请输入姓名:')
    age = input('请输入年龄:')
    job = input('请输入职业:')
    hobby = input('请输入爱好:')
    msg = '''
    ------------ info of Alex Li ----------
    Name : %s
    Age : %s
    job : %s
    Hobbie: %s
    ------------- end ----------------'''
    data = msg %(name,age,job,hobby,)
    print(data)
  • 特殊格式1

    msg = "我是%s,年龄%s" %('alex',19,)
    print(msg)
    
    msg = "我是%(n1)s,年龄%(n2)s" % {'n1': 'alex', 'n2': 123, }
    print(msg)
  • 特殊格式2

    # v1 = "我是{0},年龄{1}".format('alex',19)
    v1 = "我是{0},年龄{1}".format(*('alex',19,))
    print(v1)
    
    # v2 = "我是{name},年龄{age}".format(name='alex',age=18)
    v2 = "我是{name},年龄{age}".format(**{'name':'alex','age':18})
    print(v2)

2-5-3. 2.6 运算符

2-5-4. 2.6.1算数运算符

​ +、-、*、/、%、**、//

# 练习题: 1 ~ 100 之间全部的数相加。
# total = 0
# count = 1
# while count <=100:
# 	total = total + count
# 	count = count + 1
# print(total)
# 练习题:打印 1 ~ 100 之间的奇数。
count = 1
while count <= 100:
    val = count % 2
    if val == 1:
    print(count)
count = count + 1

2-5-5. 2.6.2 比较运算符

​ >/>=/</<=/==/!=

2-5-6. 2.6.3 赋值运算符

​ +=/-=

# count = 1
# while count <=100:
# print(count)
# count +=1 # count = count + 1

2-5-7. 2.6.4 逻辑运算符

​ and or not

  • 通常用于判断
if 1 > 0 and 1 > 2:
print('666')
  • 二般用于取值(面试)

    • or
    """
    对于 or,若是有遇到 value= 1 or 9
    第一个值若是是转换成布尔值若是是真,则value=第一值。
    第一个值若是是转换成布尔值若是是假,则value=第二值。
    若是有多个or条件,则从左到右依次进行上述流程。
    示例:
    v1 = 0 or 1
    v2 = 8 or 10
    v3 = 0 or 9 or 8
    """
    • and
    """对于and,若是遇到 value= 1 and 9 这种状况
    若是第一个值转换成布尔值是True,则value=第二个值。
    若是第一个值转换成布尔值是False,则value=第一个值。
    若是有多个and条件,则从左到右依次进行上述流程。
    示例:
    v1 = 1 and 9
    v2 = 1 and 0
    v3 = 0 and 7
    v4 = 0 and ""
    v5 = 1 and 0 and 9
    """
    • 结合
    # 先看and再看or
    # v1 = 1 and 9 or 0 and 6
    # print(v1)
    • 优先级

      在没有()的状况下not 优先级高于 and,and优先级高于or,即优先级关系为()>not>and>or,同一优先级从左往右计算。

2-5-8. 2.6.5 成员运算

​ in/ not in

2-5-9. 2.6.6 优先级

​ 算数>比较>赋值>逻辑(not>and>or)

2-5-10. 2.6.7 逗号运算符

  • a,b=b,a 交换两个值
  • a,b=取值

2-6. 2.7 流程控制

2-6-1. 2.7.1 if语句

# 请实现一个功能:让用户输入性别,若是是 男,则输出:
再见;若是是 女:则输出 来呀来呀;
gender = input("请输入性别:")
"""
若是是男生:打印再见
不然:打印来呀来呀
"""
if gender == "男":
print('再见')
else:
print('来呀来呀')

2-6-2. 2.7.2 elif 条件

# 请实现一个功能:让用户输入性别,若是是 男,则输出:
再见;若是是 女:则输出 来呀来呀;若是是 人妖:找alex
去,他也是。不然:滚
gender = input("请输入性别:")
"""
若是是男生:打印再见
不然:打印来呀来呀
"""
if gender == "男":
print('再见')
elif gender == '女':
print('来来来')
elif gender == '人妖':
print('找alex去,他也是')
else:
print('滚')
print('end')
# 第一题:让用户输入一个数字,猜:若是数字 > 50,则输
出:大了; 若是数字 <= 50 ,则输出:小了。
1
num = input('请输入一个数字')
number = int(num)
if number > 50:
print('大了')
else:
print('小了')
# 第二题:用户名密码登录
username = input('请输入用户名:')
password = input('请输入密码:')
if username == 'alex' and password ==
"oldboy" :
print('欢迎登录')
else:
print('用户名或密码错误')

2-7. 2.8 循环语句

2-7-1. 2.8.1 格式

while 条件语句:
    执行语句
#打印1 2 3 4 5 6 8 9 10
""" count = 1
 while count <= 10:
     if count != 7:
         print(count)
     count = count + 1"""
count = 1
while count <= 10:
    if count == 7:
        pass
    else:
        print(count)
    count = count + 1

2-7-2. 2.8.2 关键字break

做用:终止当前循环.

  while True:
      print("你好")
      while True:
          print(666)
          break
      break

2-7-3. 2.8.2 关键字:continue

本次循环遇到continue,则再也不继续往下走,返回条件语句继续判断.

count = 1
while count <=10:
print(count)
continue # 本次循环若是遇到continue,则不在继续往下走,而是回到while条件位置。
count = count + 1
# 示例:1234568910
count = 1
while count <=10:
if count == 7:
count = count + 1
continue
print(count)
count = count + 1

2-7-4. 2.8.3 while else 结构

"""
count = 1
while count < 10:
    print(count)
    count = count + 1
else: # 再也不知足while后的条件时,触发。 或 条件=False
    print('ELSE代码块')
    print('结束')
"""
"""
count = 1
    while True:
    print(count)
    if count == 10:
    break
    count = count + 1
else: # 再也不知足while后的条件时,触发。 或 条件=False
    print('ELSE代码块')
    print('结束')
"""

2-7-5. 2.9 三元运算(三目运算)

v =  前面  if 条件 else 后面 

if 条件:
    v = '前面'
else:
    v = '后面'
# 让用户输入值,若是值是整数,则转换成整数,不然赋值为None

data = input('>>>')
value =  int(data) if data.isdecimal() else None 

注意:先作出来,再思考如何简化。

3. 第三章 数据类型

3-1. 3.1 整型(int)

from __future__ import division 
value = 3/2
print(value)
  • py2:有int和long,除法保留整数

  • py3只有int,结果保留全部

3-2. 3.2 布尔型(bool)

True
False
v1 = bool("hello")
v2 = bool("")
print(v1,v2)

转布尔型False: None 0 "" [] {} () set{}

3-3. 3.3 字符串(str)

字符串是写代码中最多见的,python内存中的字符串是按照:unicode 编码存储。对于字符串是不可变。

  • 基本用法

  • 加法拼接

    a = '世界'
    b = '你好'
    print(a + b)
    # 结果:世界你好
  • 单引号双引号三引号用法

    s = """yinhaiping简写为'yhp'."""
    print(s)
    #运行结果:yinhaiping简写为'yhp'.
  • 乘法屡次拼接链接

    a = '坚强'
    print(a * 8)
    结果:坚强坚强坚强坚强坚强坚强坚强坚强
  • 经常使用方法

  • .upper() / .lower(): 将字母转换为大/小写

    n='yinhaiping'
    na=n.upper()
    name=na.lower()
    print(na,name)
    #运行结果:YINHAIPING yinhaiping
v = 'ALEX'
v1 = v.upper()
print(v1)
v2 = v.isupper() # 判断是否所有是大写
print(v2)
v = 'alex'
v1 = v.lower()
print(v1)
v2 = v.islower() # 判断是否所有是小写
print(v2)


############ 了解便可
v = 'ß'
# 将字符串变小写(更牛逼)
v1 = v.casefold()
print(v1) # ss
v2 = v.lower()
print(v2)
  • .isdigit(): 判断字符串是否是数字

    a='b'
    b="8"
    print(a.isdigit(),b.isdigit())
    #运行结果:False True
    v = 'alex'
    v1 = v.lower()
    print(v1)
    v2 = v.islower() # 判断是否所有是小写
    print(v2)
    
    
    ############ 了解便可
    v = 'ß'
    # 将字符串变小写(更牛逼)
    v1 = v.casefold()
    print(v1) # ss
    v2 = v.lower()
    print(v2)
  • .strip() / .lstrip() / .rstrip():去除字符串两端/左边/右边空格或换行

    a=" >>>>>>\n"
    a=a.strip()
    b="YHP"
    print(a,b)
    #运行结果:>>>>>> YHP
    
    v1 = "alex "
    print(v1.strip())
    
    v2 = "alex\t"
    print(v2.strip())
    
    v3 = "alex\n"
    print(v3.strip())
    
    v1 = "alexa"
    print(v1.strip('al'))
  • .split():将字符串按指定格式分割为列表

    s="yinhaiping"
    b=s.split("i")
    print(b)
    运行结果:['y', 'nha', 'p', 'ng']
    
  • .replace("被替换的字符/子序列","要替换为的内容",1):替换字符

    a="yinhaiping"
    b=a.replace(a[0:2],"YIN")
    c=a.replace("i","I",2)
    print(b,c)
    #运行结果:YINnhaiping yInhaIping
    
  • .startswith()/.endswith(): 判断是否以指定字符开头

    a="yinhaiping"
    print(a.startswith("yin"),a.endswith("gn"))
    #运行结果:True False
    
  • .jion():循环字符串每一个字符,按指定方式链接.例:"_".jion(str)

    a="yinhaiping"
    b="-".join(a)
    print(b)
    #运行结果:y-i-n-h-a-i-p-i-n-g
    
  • .format():格式化赋值例:"你好{}".format(s)

    a="你好{}".format("尹海平")
    print(a)
    #运行结果:你好尹海平
    
  • .encode():改变编码格式保存

    a="尹海平"
    b=a.encode("gbk")
    c=b.decode("utf-8")
    print(a,b,c)
    #运行结果:尹海平 b'\xd2\xfc\xba\xa3\xc6\xbd' 尹海平
    

3-4. 3.4 列表(list)

  • 基本格式:["str",int,bool]

  • 特色:【有序,可变】

  • 经常使用方法

    • .append(): 在列表最后追加元素

      s=[1,2,3,"唱:","我爱北京"]
      s.append("天安门")
      print(s)
      #结果:[1, 2, 3, '唱:', '我爱北京', '天安门']
      
    • .insert(索引,"元素"): 在指定索引前加元素

      s=[1,2,3,"唱:","我爱北京天安门"]
      s.insert(3,"预备")
      print(s)
      #结果:[1, 2, 3, '预备', '唱:', '我爱北京天安门']
      
    • .remove("须要删除的元素"): 直接删除指定元素

      s=[1,2,3,"唱:","我爱北京天安门"]
      s.remove("唱:")
      print(s)
      #结果:[1, 2, 3, '我爱北京天安门']
      
    • .pop(索引): 删除索引的元素 ,可返回所删除元素值

      s=[1,2,3,"唱:","我爱北京天安门"]
      b=s.pop(3)
      print(s,b)
      #结果:[1, 2, 3, '我爱北京天安门'] 唱:
      
    • .clear(): 清空全部元素

      s=[1,2,3,"唱:","我爱北京天安门"]
      s.clear()
      print(s)
      #结果:[]
      
    • del:删除带索引的列表内容.例:del name[0]

      s=[1,2,3,"唱:","我爱北京天安门"]
      del s[4]
      print(s)
      #结果:[1, 2, 3, '唱:']
      
    • .reverse():把列表反转

      s=[1,2,3,4,5]
      s.reverse()
      print(s)
      #结果:[5, 4, 3, 2, 1]
      
    • .sort(): 排序,默认升序.降序:sort(reverse=True)

      a=[5,8,6,99,81,]
      b=[5,8,6,99,81,]
      a.sort()
      b.sort(reverse=True)
      print(a,b)
      #结果:[5, 6, 8, 81, 99] [99, 81, 8, 6, 5]
      
    • .extend():批量追加另外一个序列(str,list,tuple,dict(键),set)每一个元素

       s = "qwert"
       li = ["alex", "WuSir", "ritian", "barry", "wenzhou"]
       li.extend(s)
       print(li) # 输出:['alex', 'WuSir', 'ritian', 'barry', 'wenzhou', 'q', 'w', 'e', 'r', 't']
      

3-5. 3.5 元组(tuple)

  • 基本格式:("str",int,bool)

  • 特色:【有序,不可变】

  • 自有方法【无】

    注意:元素不可修改,嵌套的可变类型内元素可修改

3-6. 3.6 字典(dict)

  • 基本格式:{键:值,键,值...}

  • 特色:【键索引,可变】

  • 经常使用方法

    • .keys(): 获取全部键

      info = { "name":"尹海平","age":"保密","address":"北京","work":"码农" }
      info_keys = message.keys()
      for i in info_keys:
          print(i)
      #运行结果:
      name
      age
      address
      work
      
    • .values(): 获取全部值

      info = { "name":"尹海平","age":"保密","address":"北京","work":"码农" }
      info_values = info.values()
      for i in info_values:
          print(i)
      #运行结果:
      尹海平
      保密
      北京
      码农
      
    • .items(): 获取全部键值对

      info = { "name":"尹海平","age":"保密","address":"北京","work":"码农" }
      info_items = info.items()
      for i in info_items:
          print(i)
      #运行结果:
      ('name', '尹海平')
      ('age', '保密')
      ('address', '北京')
      ('work', '码农')
      
    • .get(键,返回值): 获取键对应的值,默认返回None

      infos = { "name":"尹海平","age":"保密","address":"北京","work":"码农" }
      info = infos.get("name")
      info1=infos.get("addrss","不存在")
      print(info,info1)
      #运行结果:
      尹海平 不存在
      
    • .pop(): 删除指定键值对

      infos = { "name":"尹海平","age":"保密","address":"北京","work":"码农" }
      name=infos.pop("name")
      print(infos)
      #运行结果:{'age': '保密', 'address': '北京', 'work': '码农'}
      
    • .update(): 批量更新键值

      infos = { "name":"尹海平","age":"保密","address":"北京","work":"码农" }
      info_new={"gender":"男","爱好":"女"}
      infos.update(info_new)
      print(infos)
      #运行结果:{'name': '尹海平', 'age': '保密', 'address': '北京', 'work': '码农', 'gender': '男', '爱好': '女'}
      

注意:字典中键是无序的,必须是可哈希数据类型(list/dict/set不能作键)

有序字典

from collections import OrderedDict

info = OrderedDict()
info['k1'] = 123
info['k2'] = 456

print(info.keys())
print(info.values())
print(info.items())

3-7. 3.7 集合(set)

  • 基本格式:{str,int,bool,list...}空集合=set()

  • 特色:【无序,可变,不重复】

  • 经常使用方法

    • .add(): 添加元素

      heros={"金克斯","盖伦","艾希"}
      heros.add("提莫")
      print(heros)
      #运行结果:{'提莫', '艾希', '盖伦', '金克斯'}
      
    • .update(): 批量添加

      heros={"金克斯","盖伦","艾希"}
      new_heros={"塔姆","艾克","剑圣"}
      heros.update(new_heros)
      print(heros)
      #运行结果:{'艾希', '盖伦', '金克斯', '剑圣', '塔姆', '艾克'}
      
    • .discard(): 删除指定元素

      heros={"金克斯","盖伦","艾希"}
      heros.discard("盖伦")
      print(heros)
      #运行结果:{'艾希', '金克斯'}
      
    • .intersection(): 取交集

      heros={"金克斯","盖伦","艾希"}
      new_heros={"盖伦","剑圣","艾希"}
      nb_heros=heros.intersection(new_heros)
      print(nb_heros)
      #运行结果:{'艾希', '盖伦'}
      
    • .union(): 取并集

      heros={"金克斯","盖伦","艾希"}
      new_heros={"盖伦","剑圣","艾希"}
      all_heros=heros.union(new_heros)
      print(all_heros)
      #运行结果:{'艾希', '剑圣', '金克斯', '盖伦'}
      
    • .difference(): 取差集

      heros={"金克斯","盖伦","艾希"}
      new_heros={"盖伦","剑圣","艾希"}
      dft_heros=heros.difference(new_heros)
      dft1_heros=new_heros.difference(heros)
      print(dft_heros,dft1_heros)
      #运行结果:{'金克斯'} {'剑圣'}
      
    • .symmetric_difference():取对等差分集合,返回两个集合中不重复的元素集合

      heros={"金克斯","盖伦","艾希"}
      new_heros={"盖伦","剑圣","艾希"}
      sym_heros=heros.difference(new_heros)
      print(sym_heros)
      #运行结果:{'金克斯'}
      

3-8. 3.8 公共方法

  • len(): 返回元素个数

    可应用的数据类型有:str 字符串、list 列表、dict 字典、tuple 元组、set 集合

    heros={"金克斯","盖伦","艾希"}
    num=len(heros)
    print(num)
    #y=运行结果:3
    
  • 索引[num]: 左闭右开,左→右从0开始,从右→左从-1开始

    可应用的数据类型有:str 字符串、list 列表、dict 字典、tuple 元组

    heros=["金克斯","盖伦","艾希"]
    name=heros[1]
    name1=heros[-3]
    print(name,name1)
    #运行结果:盖伦 金克斯
    
  • 切片[start:stop]: 左闭右开,反向加"-"

    可应用的数据类型有:str 字符串、list 列表、tuple 元组

    heros=["金克斯","盖伦","艾希","提莫","赵信"]
    name=heros[-4:-1]
    print(name)
    #运行结果:['盖伦', '艾希', '提莫']
    
  • 步长[start:stop:step]: 默认为1,逆向取加"-"

    可应用的数据类型有:str 字符串、list 列表、tuple 元组

    heros=["金克斯","盖伦","艾希","提莫","赵信"]
    name=heros[-1:-4:-2]
    print(name)
    #运行结果:['赵信', '艾希']
    
  • del: 删除

    可应用的数据类型有:list 列表、dict 字典

    heros=["金克斯","盖伦","艾希","提莫","赵信"]
    del heros[3]
    print(heros)
    #运行结果:['金克斯', '盖伦', '艾希', '赵信']
    
  • .update(): 批量增长

    可应用的数据类型有:list 列表、dict 字典、set集合

    heros={"金克斯","盖伦","艾希"}
    new_heros={"塔姆","艾克","剑圣"}
    heros.update(new_heros)
    print(heros)
    #运行结果:{'艾希', '盖伦', '金克斯', '剑圣', '塔姆', '艾克'}
    

4. 第四章 文件操做

4-1. 4.1 文件基本操做

obj = open('路径',mode='模式',encoding='编码')
obj.write()
obj.read()
obj.close()

4-2. 4.2 打开模式

  • r / w / a
  • r+ / w+ / a+
  • rb / wb / ab
  • r+b / w+b / a+b

4-3. 4.3 操做

  • read() , 所有读到内存

  • read(1)

    • 1表示一个字符

      obj = open('a.txt',mode='r',encoding='utf-8')
      data = obj.read(1) # 1个字符
      obj.close()
      print(data)
    • 1表示一个字节

      obj = open('a.txt',mode='rb')
      data = obj.read(3) # 1个字节
      obj.close()
  • write(字符串)

    obj = open('a.txt',mode='w',encoding='utf-8')
    obj.write('中午你')
    obj.close()
  • write(二进制)

    obj = open('a.txt',mode='wb')
    
    # obj.write('中午你'.encode('utf-8'))
    v = '中午你'.encode('utf-8')
    obj.write(v)
    
    obj.close()
  • seek(光标字节位置),不管模式是否带b,都是按照字节进行处理。

    obj = open('a.txt',mode='r',encoding='utf-8')
    obj.seek(3) # 跳转到指定字节位置
    data = obj.read()
    obj.close()
    
    print(data)
    
    obj = open('a.txt',mode='rb')
    obj.seek(3) # 跳转到指定字节位置
    data = obj.read()
    obj.close()
    
    print(data)
  • tell(), 获取光标当前所在的字节位置

    obj = open('a.txt',mode='rb')
    # obj.seek(3) # 跳转到指定字节位置
    obj.read()
    data = obj.tell()
    print(data)
    obj.close()
  • flush,强制将内存中的数据写入到硬盘

    v = open('a.txt',mode='a',encoding='utf-8')
    while True:
        val = input('请输入:')
        v.write(val)
        v.flush()
    
    v.close()

4-4. 4.4 关闭文件

文艺青年

v = open('a.txt',mode='a',encoding='utf-8')

v.close()

二逼

with open('a.txt',mode='a',encoding='utf-8') as v:
    data = v.read()
    # 缩进中的代码执行完毕后,自动关闭文件

4-5. 4.5 文件内容的修改

with open('a.txt',mode='r',encoding='utf-8') as f1:
    data = f1.read()
new_data = data.replace('飞洒','666')

with open('a.txt',mode='w',encoding='utf-8') as f1:
    data = f1.write(new_data)

大文件修改

f1 = open('a.txt',mode='r',encoding='utf-8')
f2 = open('b.txt',mode='w',encoding='utf-8')

for line in f1:
    new_line = line.replace('阿斯','死啊')
    f2.write(new_line)
f1.close()
f2.close()
with open('a.txt',mode='r',encoding='utf-8') as f1, open('c.txt',mode='w',encoding='utf-8') as f2:
    for line in f1:
        new_line = line.replace('阿斯', '死啊')
        f2.write(new_line)

5.

6. 第五章 函数

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

写代码的方式:面向过程 --> 函数式编程(多) --> 面向对象编程。

对于函数编程:

  • 本质:将N行代码拿到别处并给他起个名字,之后经过名字就能够找到这段代码并执行。
  • 场景:
    • 代码重复执行。
    • 代码量特别多超过一屏,能够选择经过函数进行代码的分割。

6-1. 5.1函数的基本结构

# 函数的定义
def 函数名():
    # 函数内容
    pass

# 函数的执行
函数名()
def get_list_first_data():
    v = [11,22,33,44]
    print(v[0])


get_list_first_data()

# 注意:函数若是不被调用,则内部代码永远不会被执行。
# 假如:管理员/业务员/老板用的是同一个邮箱。
def send_email():
    print('发送邮件成功,假设有10含代码')


user_input = input('请输入角色:')

if user_input == '管理员':
    send_email()
elif user_input == '业务员':
    send_email()
elif user_input == '老板':
    send_email()

6-2. 5.2 参数

6-2-1. 5.2.1参数格式与种类

  1. 函数能够传递任意数据类型,任意个数的参数
def func(a1,a2,a3):# a1,a2,a3叫形式参数(形参)
    print(a1,a2,a3)
    
func(1,"asdf",True)#调用时传递的参数叫实际参数(实参)
  1. 位置传参(调用函数语句)
def func(a1,a2):
    print(a1,a2)

    func(1,3)
  1. 关键字传参(调用函数语句)
def func(a1, a2):
    print(a1, a2)

func(a2=99,a1=2)

# 关键字传参数和位置传参能够混合使用,位置传入的参数在前,关键字参数在后 
def func1(a1, a2, a3):
    print(a1, a2, a3)

# func(1, 2, a3=9)
# func(1, a2=2, a3=9)
# func(a1=1, a2=2, a3=9)
# func(a1=1, 2,3) # 错误
  1. 参数默认值

    编写函数时,可给每一个形参指定默认值。在调用函数中给形参提供了实参时,Python将使用指定的实参值;不然,将使用形参的默认值。所以,给形参指定默认值后,可在函数调用中省略相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。

    def func(a1,a2,a3=9,a4=10):
        print(a1,a2,a3,a4)
    
    func(11,22)
    func(11,22,10)
    func(11,22,10,100)
    func(11,22,10,a4=100)
    func(11,22,a3=10,a4=100)
    func(11,a2=22,a3=10,a4=100)
    func(a1=11,a2=22,a3=10,a4=100)

    函数的默认值慎用可变类型

    # 若是要想给value设置默认是空列表
    
    # 不推荐(坑)
    def func(data,value=[]): 
        pass 
    
    # 推荐
    def func(data,value=None):
        if not value:
            value = []
    def func(data,value=[]): 
        value.append(data)
        return value 
    
    v1 = func(1) # [1,]
    v2 = func(1,[11,22,33]) # [11,22,33,1]

    面试题:

    • def func(a,b=[]) 有什么陷阱?

    • 看代码写结果

      def func(a,b=[]):
          b.append(a)
          return b
      
      l1 = func(1)
      l2 = func(2,[11,22])
      l3 = func(3)
      
      # [1,3]   [11,22,2]   [1,3]
      print(l1,l2,l3)
      def func(a,b=[]):
          b.append(a)
          print(b)
          
      func(1)
      func(2,[11,22,33])
      func(3)
      
      # [1]  [11,22,33,2]   [1,3]
  2. 万能参数(打散)

    • *args

      • 能够接受任意个数的位置参数,并将参数转换成元组。

        • 调用函数无 *
        def func(*args):
            print(args)
        
        func(1,2,3,4)
        • 调用函数有 *

          循环列表的每一个元素传入函数

        def func(*args):
            print(args)
        
        func(*(1,2,3,4))
        func(*[1,2,3,4])
    • 只能用位置传参

      def func(*args):
          print(args)
      
      # func(1)
      # func(1,2)
      func(1,2) # args=(1, 2)
      func((11,22,33,44,55)) # args=((11,22,33,44,55),)
      func(*(11,22,33,44,55)) # args=(11,22,33,44,55)
    • **kwargs

      • 能够接受任意个数的关键字参数,并将参数转换成字典。

        • 调用函数无 **

          def func(**kwargs):
              print(kwargs)
          
          
          func(k1=1,k2="alex")
        • 调用函数有**

          循环字典的每一个键值对传入函数

          def func(**kwargs):
              print(kwargs)
          func(**{'k1':'v2','k2':'v2'}) # kwargs={'k1':'v2','k2':'v2'}
      • 只能用关键字传参

      • 综合应用:无敌 + 无敌 => 真无敌

        def func(*args,**kwargs):
            print(args,kwargs)
        
        # func(1,2,3,4,5,k1=2,k5=9,k19=999)
        func(*[1,2,3],k1=2,k5=9,k19=999)
        func(*[1,2,3],**{'k1':1,'k2':3})
        func(111,222,*[1,2,3],k11='alex',**{'k1':1,'k2':3})

    参数相关重点:

    1. 定义函数
    def func1(a1,a2):
        pass 
    
    def func2(a1,a2=None):
        pass 
    
    def func3(*args,**kwargs):
        pass 
    
    1. 调用函数
      位置参数 > 关键字参数

6-2-2. 5.2.2 做用域

python中:

  • py文件:全局做用域
  • 函数:局部做用域
a = 1
def s1():   #注意:在调用以前选择参数值究竟是多少. 
    x1 = 666
    print(x1)
    print(a)
    print(b)
b = 2
print(a) #1
s1()	#666\n 1\n2
a = 88888
def s2():
    print(a,b) 
    s1()		
s2()	 #88888	2				#666\n 88888\n2

总结:

  • 一个函数是一个做用域

    def func():
        x = 9
        print(x)
    func()
    print(x)
  • 做用域中查找数据规则:优先在本身的做用域找数据,本身没有就去 "父级" -> "父级" -> 直到全局,所有么有就报错。注意:父级做用域中的值究竟是什么?

    x = 10
    def func():
        x = 9
        print(x)
    
    func()

    注意:函数参数取决于调用时的参数值而不是定义时的值

  • 子做用域中只能 找到父级中的值 ,默认没法从新为父级的变量进行赋值。(global/nonlocal能够强制作)

    # #####################
    name = 'oldboy'
    def func():
        name = 'alex' # 在本身做用域再建立一个这样的值。
        print(name)
    func()
    print(name)
    
    
    
    # #####################
    name = [1,2,43]
    def func():
        name.append(999)
        print(name)
    func()
    print(name)
    
    # ###################### 若是非要对全局的变量进行赋值
    # 示例一
    name = ["老男孩",'alex']
    def func():
        global name
        name = '我'
    func()
    print(name)
    # 示例一
    name = "老男孩"
    def func():
        name = 'alex'
        def inner():
            global name
            name = 999
        inner()
        print(name)
    func()
    print(name)
    
    
    name = "老男孩"
    def func():
        name = 'alex'
        def inner():
            global name
            name = 999
        inner()
        print(name)
    func()
    print(name)
    
    # ############################## nonlocal
    name = "老男孩"
    def func():
        name = 'alex'
        def inner():
            nonlocal name # 找到上一级的name
            name = 999
        inner()
        print(name)
    func()
    print(name)

练习题

# 1. 请写一个函数,函数计算列表 info = [11,22,33,44,55] 中全部元素的和。

def get_sum():
    info = [11,22,33,44,55]
    data = 0
    for item in info:
        data += item
    print(data)

get_sum()

# 2. 请写一个函数,函数计算列表中全部元素的和。

def get_list_sum(a1):
   	data = 0
    for item in a1:
        data += item
   	print(data)
    
get_list_sum([11,22,33])
get_list_sum([99,77,66])
v1 = [8712,123,123]
get_list_sum(v1)

# 3. 请写一个函数,函数将两个列表拼接起来。
def join_list(a1,a2):
    result = []
    result.extend(a1)
    result.extend(a2)
    print(result)
    
join_list([11,22,33],[55,66,77]

# 4. 计算一个列表的长度
def my_len(arg):
    count = 0
    for item in arg:
          count += 1
    print(count)

v = [11,22,33]
my_len(v)
len(v)

# 5. 发邮件的示例
          
def send_email(role,to):
    template = "要给%s%s发送邮件" %(role,to,)
    print(template)
 

user_input = input('请输入角色:')

if user_input == '管理员':
    send_email('管理员','xxxx@qq.com')
elif user_input == '业务员':
    send_email('业务员','xxxxo@qq.com')
elif user_input == '老板':
    send_email('老板','xoxox@qq.com')

6-3. 5.3 返回值

def func(arg):
    # ....
    return 9 # 返回值为9 默认:return None

val = func('adsfadsf')
# 1. 让用户输入一段字符串,计算字符串中有多少A字符的个数。有多少个就在文件a.txt中写多少个“李邵奇”。

def get_char_count(data):
    sum_counter = 0
    for i in data:
        if i == 'A':
            sum_counter += 1
            
    return sum_counter

def write_file(line):
    if len(line) == 0:
        return False  # 函数执行过程当中,一旦遇到return,则中止函数的执行。
    with open('a.txt',mode='w',encoding='utf-8') as f:
        f.write(line)
    return True 


content = input('请输入:')
counter = get_char_count(content)
write_data = "李邵奇" * counter 
status = write_file(write_data)
if status:
    print('写入成功')
else:
    print('写入失败')

6-4. 5.4 上述总结

# 状况1
def f1():
    pass 
f1()

# 状况2
def f2(a1):
    pass 
f2(123)

# 状况3
def f3():
    return 1 
v1 = f3()

# 状况4
def f4(a1,a2):
    # ... 
    return 999
v2 = f4(1,7)

6-5. 5.5 练习题

# 1. 写函数,计算一个列表中有多少个数字,打印: 列表中有%s个数字。
#    提示:type('x') == int 判断是不是数字。
"""
# 方式一:
def get_list_counter1(data_list):
    count = 0
    for item in data_list:
        if type(item) == int:
            count += 1
    msg = "列表中有%s个数字" %(count,)
    print(msg)
    
get_list_counter1([1,22,3,'alex',8])

# 方式二:
def get_list_counter2(data_list):
    count = 0
    for item in data_list:
        if type(item) == int:
            count += 1
    return count
    
v = get_list_counter1([1,22,3,'alex',8])
msg = "列表中有%s个数字" %(v,)
print(msg)
"""

# 2. 写函数,计算一个列表中偶数索引位置的数据构形成另一个列表,并返回。
"""
# 方式一:
def get_data_list1(arg):
    v = arg[::2]
    return v

data = get_data_list1([11,22,33,44,55,66])

# 方式二:
def get_data_list2(arg):
    v = []
    for i in range(0,len(arg)):
    	if i % 2 == 0:
    		v.append(arg[i])
   	return v

data = get_data_list2([11,22,33,44,55,66])

"""

# 3. 读取文件,将文件的内容构形成指定格式的数据,并返回。
"""
a.log文件
    alex|123|18
    eric|uiuf|19
    ...
目标结构:
a.  ["alex|123|18","eric|uiuf|19"] 并返回。
b. [['alex','123','18'],['eric','uiuf','19']]
c. [
    {'name':'alex','pwd':'123','age':'18'},
    {'name':'eric','pwd':'uiuf','age':'19'},
]
"""
def lst(f):
    a = []
    for line in f:
        new_line = line.strip()
        a.append(new_line)
    return a


def list_lst(f):
    b = []
    f.seek(0)
    for line in f:
        new_line = line.strip()
        li = new_line.split("|")
        b.append(li)
    return b


def dit(f):
    c = []
    f.seek(0)
    for line in f:
        dic = {}
        new_line = line.strip()
        li = new_line.split("|")
        dic["name"] = li[0]
        dic["pwd"] = li[1]
        dic["age"] = li[2]
        c.append(dic)
    return c


with open('a.txt', mode='r', encoding='utf-8') as f:
    a = lst(f)
    b = list_lst(f)
    c = dit(f)
    print(a, "\n", b, "\n", c)

6-6. 5.6 函数变量

函数自己也是一种数据类型,函数名对应程序入口地址

6-6-1. 5.6.1 函数名看成变量来使用

def func():
    print(123) 
v1 = func #函数名能够赋值给其余变量,来指向函数
func()
v1()     #函数加()才会执行
#123	
#123
def func():
    print(123)
    
func_list = [func, func, func]
for item in func_list:
    v = item()
    print(v)

6-6-2. 5.6.2 函数能够看成参数进行传递

def func(arg):
    v1 = arg()
    print(v1)

def show():
    print(666)

func(show)
#666
#None
def func(arg):
    v1 = arg()
    print(v1)
    
def show():
    print(666)
    
result = func(show)
print(result)
# 面试题

def func():
    print('花费查询')


def bar():
    print('语音沟通')


def base():
    print('xxx')


def show():
    print('xxx')


def test():
    print('xxx')

info = {
    'f1': func,
    'f2': bar,
    'f3':base,
    'f4':show,
    'f5':test
}
choice = input('请选择要选择功能:')
function_name = info.get(choice)
if function_name:
    function_name()
else:
    print('输入错误')

6-6-3. 5.6.3 函数能够作返回值

函数被调用,开辟一块内存空间执行,同时被调用开辟不一样的内存空间,之间不会混乱,执行完毕后释放内存.

def func():
    print(123)
def bar():
    return func
v = bar()
v()
name = 'oldboy'
def func():
    print(name)  
def bar():
    return func
v = bar()
v()
name = 'oldboy'
def bar(name):
    def inner():
        print(name)
    return inner
v1 = bar('alex') # { name=alex, inner }  # 闭包,为函数建立一块区域(内部变量供本身使用),为他之后执行提供数据。
v2 = bar('eric') # { name=eric, inner }
v1()
v2()

6-6-4. 5.6.4 闭包

闭包概念:为函数建立一块区域并为其维护本身数据,之后执行时方便调用。【应用场景:装饰器 / SQLAlchemy源码】

def func(name):
    def inner():
        print(name)
    return inner 

v1 = func('alex')
v1()
v2 = func('eric')
v2()
info = []

def func(i):
    def inner():
        print(i)
    return inner

for item in range(10):
    info.append(func(item))

info[0]()
info[1]()
info[4]()
def x(func):
    def inner(a1,a2):
        return func()
    return inner 

@x
def index():
    pass
# func = 原来的index函数u
# index = inner
index(1,2)
  • 关于返回值
def x1(func):
    def inner(*args,**kwargs):
        data = func(*args,**kwargs)
        return data
    return inner 

@x1
def f1():
    print(123)
    return 666
v1 = f1()
print(v1)
def x1(func):
    def inner(*args,**kwargs):
        data = func(*args,**kwargs)
    return inner 

@x1
def f1():
    print(123)
    return 666

v1 = f1()
print(v1)
  • 关于先后

    def x1(func):
        def inner(*args,**kwargs):
            print('调用原函数以前')
            data = func(*args,**kwargs) # 执行原函数并获取返回值
            print('调用员函数以后')
            return data
        return inner 
    
    @x1
    def index():
        print(123)
        
    index()
  • 带参数的装饰器(flask框架 + django缓存 + 写装饰器实现被装饰的函数要执行N次)

    # 第一步:执行 ret = xxx(index)
    # 第二步:将返回值赋值给 index = ret 
    @xxx
    def index():
        pass
    
    # 第一步:执行 v1 = uuu(9)
    # 第二步:ret = v1(index)
    # 第三步:index = ret 
    @uuu(9)
    def index():
        pass
    # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,把每次结果添加到列表中,最终返回列表。
    def xxx(counter):
        print('x函数')
        def wrapper(func):
            print('wrapper函数')
            def inner(*args,**kwargs):
                v = []
                for i in range(counter):
                    data = func(*args,**kwargs) # 执行原函数并获取返回值
                    v.append(data)
                return v
            return inner
        return wrapper
    
    @xxx(5)
    def index():
        return 8
    
    v = index()
    print(v)

6-7. 5.7 lambda表达式

用于表示简单的函数,也称做匿名函数。

# 三元运算,为了解决简单的if else的状况,如:
if 1 == 1:
    a = 123
else:
    a = 456

a =  123  if 1 == 1 else 456

# lambda表达式,为了解决简单函数的状况,如:
def func(a1,a2):
    return a1 + 100 

func = lambda a1,a2: a1+100
func1 = lambda : 100 

func2 = lambda x1: x1 * 10

func3 = lambda *args,**kwargs: len(args) + len(kwargs)

总结:列表全部方法基本上都是返回None;字符串的全部方法基本上都是返回新值

6-8. 5.8 内置函数

  • 输入输出

    • print
    • input
  • 强制转换

    • int()
    • bool()
    • list()
    • str()
    • tuple()
    • dict()
    • set()
  • 数学相关

    • abs() 绝对值

    • float() 转换成浮点数

    • max() 找到最大值

    • min() 找到最小值

    • sum() 求和

    • pow() 乘方

      v = pow(2,3)
      print(v)#  2的3次方
    • round

      v = round(1.127,2)
      print(v)  #四舍五入保留几位小数
    • divmod() 两数相除的商和余数

      a,b = divmod(1001,5)
      print(a,b)
      # 练习题  请经过分页对数据进行展现
      """
      要求:
          每页显示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:
              """
              # 第1页:USER_LIST[0:10] -> 0123456789
              # 第2页:USER_LIST[10:20]
              # 第3页:USER_LIST[20:30]
              ...
              """
              start = (pager-1) * per_page_count
              end = pager * per_page_count
              data = USER_LIST[start:end]
              for item in data:
                  print(item)
  • 进制转换相关

    • bin,将十进制转化成二进制

      num = 13
      v1 = bin(num)
      print(v1)
    • oct,将十进制转换成八进制

      num = 8
      v1 = oct(num)
      print(v1)
    • int,将其余进制转化成十进制

      # 二进制转化成十进制
      v1 = '0b1101'
      result = int(v1,base=2)
      print(result)
      
      # 八进制转化成十进制
      v1 = '0o1101'
      result = int(v1,base=8)
      print(result)
      
      # 十六进制转化成十进制
      v1 = '0x1101'
      result = int(v1,base=16)
      print(result)
    • hex,将十进制转换成十六进制

      num = 16
      v1 = hex(num)
      print(v1)
    • 面试题

      # 1字节等于8位
      # IP: 192.168.12.79  ->  001010010 . 001010010 . 001010010 . 001010010
      
      # 1. 请将 ip = "192.168.12.79" 中的每一个十进制数转换成二进制并经过,链接起来生成一个新的字符串。
      ip = "192.168.12.79"
      ip_list = ip.split('.') # ['192','168','12','79']
      result = []
      for item in ip_list:
          result.append(bin(int(item)))
      print(','.join(result))
      
      
      # 2. 请将 ip = "192.168.12.79" 中的每一个十进制数转换成二进制: 
      #          0010100100001010010001010010001010010 -> 十进制的值。
      
      # 3232238671
      ip='192.168.12.79'
      bit_str=''
      ip_list=ip.split(".")
      for i in ip_list:
          bit=bin(int(i))[2:]
          long=len(bit)
          if long<8:
              bit=(8-long)*"0"+bit
          bit_str+=''.join(bit)
      num=int(bit_str,base=2)
      print(num)
  • 编码相关

    • chr,将十进制数字转换成 unicode 编码中的对应字符串。

      v = chr(99)
      print(v)
    • ord,根据字符在unicode编码中找到其对应的十进制。

      num = ord('中')
    • 应用:random模块

      import random
      
      def get_random_code(length=6):
          data = []
          for i in range(length):
              v = random.randint(65,90)
              data.append(chr(v))
      
          return  ''.join(data)
      
      
      code = get_random_code()
      print(code)
      import random # 导入一个模块 
      
      v = random.randint(起始,终止) # 获得一个随机数
  • 高级一点的内置函数

    • map,循环每一个元素(第二个参数),而后让每一个元素执行函数(第一个参数),将每一个函数执行的结果保存到新的列表中,并返回。map(批量操做函数,序列)

      v1 = [11,22,33,44]
      result = map(lambda x:x+100,v1)
      print(list(result)) # 特殊
    • filter filter(判断条件,序列)

      v1 = [11,22,33,'asd',44,'xf']
      
      def func(x):
          if type(x) == int:
              return True
          return False
      result = filter(func,v1) # [11,]
      print(list(result))
      
      
      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)
      
      result = functools.reduce(lambda x,y:x+y,v1)
      print(result)

6-9. 5.10 装饰器

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

def func(arg):
    def inner():
        v = arg()
        return v 
    return inner 

# 第一步:执行func函数并将下面的函数参数传递,至关于:func(index)
# 第二步:将func的返回值从新赋值给下面的函数名。 index = func(index)
@func 
def index():
    print(123)
    return 666

print(index)
# ################## 普通装饰器 #####################
def wrapper(func):
    def inner(*args,**kwargs):
        print('调用原函数以前')
        data = func(*args,**kwargs) # 执行原函数并获取返回值
        print('调用员函数以后')
        return data
    return inner 

@wrapper
def index():
    pass

# ################## 带参数装饰器 #####################
def x(counter):
    def wrapper(func):
        def inner(*args,**kwargs):
            data = func(*args,**kwargs) # 执行原函数并获取返回值
            return data
        return inner 
    return wrapper 

@x(9)
def index():
    pass

编写装饰器 和应用

# 装饰器的编写
def x(func):
    def y():
        # 前
        ret = func()
        # 后
        return ret 
   	return y 

# 装饰器的应用
@x
def index():
    return 10

@x
def manage():
    pass

# 执行函数,自动触发装饰器了
v = index()
print(v)
  • 应用场景:想要为函数扩展功能时,能够选择用装饰器。

  • 记住:

    • 装饰器建议编写格式

      def 外层函数(参数): 
          def 内层函数(*args,**kwargs):
              return 参数(*args,**kwargs)
          return 内层函数
    • 装饰器应用格式

      @外层函数
      def index():
          pass
      
      index()
    • 问题:为何要加 *args, **kwargs

6-10. 5.11 迭代器

本身不会写迭代器,只用。

任务:请展现列表中全部的数据。

  • while + 索引 + 计数器

  • 迭代器,对 某种对象(str/list/tuple/dict/set类建立的对象)-可迭代对象 中的元素进行逐一获取,表象:具备__next__方法且每次调用都获取可迭代对象中的元素(从前到后一个一个获取)。

    • 列表转换成迭代器:

      • v1 = iter([11,22,33,44])
      • v1 = [11,22,33,44].__iter__()
    • 迭代器想要获取每一个值:反复调用 val = v1.__next__()

      v1 = [11,22,33,44]
      
      # 列表转换成迭代器
      v2 = iter(v1)
      result1 = v2.__next__()
      print(result1)
      result2 = v2.__next__()
      print(result2)
      result3 = v2.__next__()
      print(result3)
      result4 = v2.__next__()
      print(result4)
      result5 = v2.__next__()
      print(result5)
      """
      # v1 = "alex"
      # v2 = iter(v1)
      # while True:
      #     try:
      #         val = v2.__next__()
      #         print(val)
      #     except Exception as e:
      #         break
    • 直到报错:StopIteration错误,表示已经迭代完毕。

    • 如何判别一个对象是不是迭代器:内部是否有__next__方法

  • for循环

    v1 = [11,22,33,44]
    
    # 1.内部会将v1转换成迭代器
    # 2.内部反复执行 迭代器.__next__()
    # 3.取完不报错
    for item in v1:
        print(item)
  • 可迭代对象

    • 内部具备 __iter__() 方法且返回一个迭代器。(*)
    v1 = [11,22,33,44]
    result = v1.__iter__()
    • 能够被for循环

6-11. 5.12 生成器(函数的变异)

# 函数
def func():
    return 123
func()
# 生成器函数(内部是否包含yield)
def func():
    print('F1')
    yield 1
    print('F2')
    yield 2
    print('F3')
    yield 100
    print('F4')
# 函数内部代码不会执行,返回一个 生成器对象 。
v1 = func()
# 生成器是能够被for循环,一旦开始循环那么函数内部代码就会开始执行。
for item in v1:
    print(item)
def func():
    count = 1
    while True:
        yield count
        count += 1
        
val = func()

for item in val:
    print(item)

总结:函数中若是存在yield,那么该函数就是一个生成器函数,调用生成器函数会返回一个生成器,生成器只有被for循环时,生成器函数内部的代码才会执行,每次循环都会获取yield返回的值。

def func():
    count = 1
    while True:
        yield count
        count += 1
        if count == 100:
            return

val = func()
for item in val:
    print(item)

示例:读文件

def func():
    """
    分批去读取文件中的内容,将文件的内容返回给调用者。
    :return:
    """
    cursor = 0
    while True:
        f = open('db', 'r', encoding='utf-8')# 经过网络链接上redis
        # 代指   redis[0:10]
        f.seek(cursor)
        data_list =[]
        for i in range(10):
            line = f.readline()
            if not line:
                return
            data_list.append(line)
        cursor = f.tell()
        f.close()  # 关闭与redis的链接


        for row in data_list:
            yield row


for item in func():
    print(item)

其余知识:

  • yeild from关键字【欠】
  • 生成器推导式【欠】

6-12. 5.13 推导式

  • 列表推导式

    """
    目的:方便的生成一个列表。
    格式:
        v1 = [i for i in 可迭代对象 ]
        v2 = [i for i in 可迭代对象 if 条件 ] # 条件为true才进行append
    """
    v1 = [ i for i in 'alex' ]  
    v2 = [i+100 for i in range(10)]
    v3 = [99 if i>5 else 66  for i in range(10)]
    
    def func():
        return 100
    v4 = [func for i in range(10)]
    
    v5 = [lambda : 100 for i in range(10)]
    result = v5[9]()
    
    def func():
        return i
    v6 = [func for i in range(10)]
    result = v6[5]()
    
    v7 = [lambda :i for i in range(10)]
    result = v7[5]()
    
    
    v8 = [lambda x:x*i for i in range(10)] # 新浪微博面试题
    # 1.请问 v8 是什么?
    # 2.请问 v8[0](2) 的结果是什么?
    
    # 面试题
    def num():
        return [lambda x:i*x for i in range(4)]
    # num() -> [函数,函数,函数,函数]
    print([ m(2) for m in num() ]) # [6,6,6,6]
    
    # ##################### 筛选 #########################
    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) }

    注意:键值重复会被覆盖

6-13. 5.14 递归

函数本身调用本身。(效率低)

def func():
    print(1)
    func()
    
func()
def func(a,b): 
    print(b) 
    func(b,a+b)
    
func(0,1) #1 1 2 3 5
def func(a):
    if a == 5:
        return 100000		# 注意递归的返回值
    result = func(a+1) + 10
    return result 

v = func(1) #100040

7. 第六章 模块(类库)

模块分类

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

  2. 第三方模块-----下载/安装/使用

    # 把pip.exe 所在的目录添加到环境变量中。
    
    pip install 要安装的模块名称  # pip install xlrd
    #报错更新
    python36  -m pip install --upgrade pip
  3. 自定义模块

7-1. 6.1 内置模块

7-1-1. 6.1.1 sys

python解释器相关的数据。

  • sys.getrefcount , 获取一个值的引用计数

    a = [11,22,33]
    b = a
    print(sys.getrefcount(a))
  • sys.getrecursionlimit , python默认支持的递归数量

  • sys.stdout.write --> print

    import time
    for i in range(1,101):
        msg = "%s%%\r" %i
        print(msg,end='')
        time.sleep(0.05)
    import os
    
    # 1. 读取文件大小(字节)
    file_size = os.stat('20190409_192149.mp4').st_size
    
    # 2.一点一点的读取文件
    read_size = 0
    with open('20190409_192149.mp4',mode='rb') as f1,open('a.mp4',mode='wb') as f2:
        while read_size < file_size:
            chunk = f1.read(1024) # 每次最多去读取1024字节
            f2.write(chunk)
            read_size += len(chunk)
            val = int(read_size / file_size * 100)
            print('%s%%\r' %val ,end='')
  • sys.argv(经常使用)

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    """
    让用户执行脚本传入要删除的文件路径,在内部帮助将目录删除。
    C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py D:/test
    C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py
    
    """
    import sys
    
    # 获取用户执行脚本时,传入的参数。
    # C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py D:/test
    # sys.argv = [D:/code/s21day14/7.模块传参.py, D:/test]
    path = sys.argv[1]
    
    # 删除目录
    import shutil
    shutil.rmtree(path)
  • sys.path ---默认Python去导入模块时,会按照sys.path中的路径挨个查找。

    # import sys
    # sys.path.append('D:\\')
    # import oldboy
  • sys.exit(0)退出程序

7-1-2. 6.1.2 os

和操做系统相关的数据。

  • os.path.exists(path) , 若是path存在,返回True;若是path不存在,返回False

  • os.stat('20190409_192149.mp4').st_size , 获取文件大小

  • os.path.abspath() , 获取一个文件的绝对路径

    path = '20190409_192149.mp4' # D:\code\s21day14\20190409_192149.mp4
    
    import os
    v1 = os.path.abspath(path)
    print(v1)
  • os.path.dirname ,获取路径的上级目录

    import os
    v = r"D:\code\s21day14\20190409_192149.mp4"
    
    print(os.path.dirname(v))
  • os.path.join ,路径的拼接

    import os
    path = "D:\code\s21day14" # user/index/inx/fasd/
    v = 'n.txt'
    
    result = os.path.join(path,v)
    print(result)
    result = os.path.join(path,'n1','n2','n3')
    print(result)
  • os.listdir , 查看一个目录下全部的文件【第一层】

    import os
    
    result = os.listdir(r'D:\code\s21day14')
    for path in result:
        print(path)
  • os.walk , 查看一个目录下全部的文件【全部层】

    import os
    
    result = os.walk(r'D:\code\s21day14')
    for a,b,c in result:
        # a,正在查看的目录 b,此目录下的文件夹  c,此目录下的文件
        for item in c:
            path = os.path.join(a,item)
            print(path)
  • os.makedirs,建立目录和子目录

    import os
    file_path = r'db\xx\xo\xxxxx.txt'
    
    file_folder = os.path.dirname(file_path)
    if not os.path.exists(file_folder):
        os.makedirs(file_folder)
    
    with open(file_path,mode='w',encoding='utf-8') as f:
        f.write('asdf')
  • os.rename,重命名

    import os
    os.rename('db','sb')
  • 补充:

    • 转义

      v1 = r"D:\code\s21day14\n1.mp4"  (推荐)
      print(v1)
      
      v2 = "D:\\code\\s21day14\\n1.mp4"
      print(v2)

7-1-3. 6.1.3 shutil

import shutil

# 删除目录
# shutil.rmtree('test')

# 重命名
# shutil.move('test','ttt')

# 压缩文件
# shutil.make_archive('zzh','zip','D:\code\s21day16\lizhong')

# 解压文件
# shutil.unpack_archive('zzh.zip',extract_dir=r'D:\code\xxxxxx\xxxx',format='zip')

实例

import os
import shutil
from datetime import datetime
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\s21day16\lizhongwei')

file_path = os.path.join('code',ctime) + '.zip'
shutil.unpack_archive(file_path,r'D:\x1','zip')

7-1-4. 6.1.4 json★

json是一个特殊的字符串。 【长的像列表/字典/字符串/数字/真假】

  • dumps序列化 & load反序列化
import json
# 序列化,将python的值转换为json格式的字符串。
# v = [12,3,4,{'k1':'v1'},True,'asdf']
# v1 = json.dumps(v)
# print(v1)

# 反序列化,将json格式的字符串转换成python的数据类型
# v2 = '["alex",123]'
# print(type(v2))
# v3 = json.loads(v2)
# print(v3,type(v3))
  • json.dumps 序列化时对中文默认使用的ascii编码.想输出真正的中文须要指定ensure_ascii=False:

    v = {'k1':'alex','k2':'李杰'}
    
    import json
    val = json.dumps(v,ensure_ascii=False)
    print(val)
  • dump序列化并写入文件

    import json
    
    v = {'k1':'alex','k2':'李杰'}
    
    f = open('x.txt',mode='w',encoding='utf-8')
    val = json.dump(v,f)
    print(val)
    f.close()
  • load从文件读取并反序列化

    import json
    
    v = {'k1':'alex','k2':'李杰'}
    
    f = open('x.txt',mode='r',encoding='utf-8')
    
    data = json.load(f)
    f.close()
    
    print(data,type(data)
Python JSON
dict object
list, tuple array
str string
int, float number
True true
False false
None null

7-1-5. 6.1.5 pickle

  • json,优势:全部语言通用;缺点:只能序列化基本的数据类型 list/dict/int...

  • pickle,优势:python中全部的东西都能被他序列化(socket对象);缺点:序列化的内容只有python认识。

    import pickle
    
    # #################### dumps/loads ######################
    """
    v = {1,2,3,4}
    val = pickle.dumps(v)
    print(val)
    data = pickle.loads(val)
    print(data,type(data))
    """
    
    """
    def f1():
        print('f1')
    
    v1 = pickle.dumps(f1)
    print(v1)
    v2 = pickle.loads(v1)
    v2()
    """
    
    # #################### dump/load ######################
    # v = {1,2,3,4}
    # f = open('x.txt',mode='wb')
    # val = pickle.dump(v,f)
    # f.close()
    
    # f = open('x.txt',mode='rb')
    # data = pickle.load(f)
    # f.close()
    # print(data)

7-1-6. 6.1.6 time&datetime

UTC/GMT:世界时间

本地时间:本地时区的时间。

  • time模块

    • time.time() ,时间戳:1970-1-1 00:00
    • time.sleep(10),等待秒数。
    • time.timezone
  • datetime模块

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import time
    from datetime import datetime,timezone,timedelta
    
    # ######################## 获取datetime格式时间 ##############################
    """
    v1 = datetime.now() # 当前本地时间
    print(v1)
    tz = timezone(timedelta(hours=7)) # 当前东7区时间
    v2 = datetime.now(tz)
    print(v2)
    v3 = datetime.utcnow() # 当前UTC时间
    print(v3)
    """
    
    # ######################## 把datetime格式转换成字符串 ##############################
    # v1 = datetime.now()
    # print(v1,type(v1))
    # val = v1.strftime("%Y-%m-%d %H:%M:%S")
    # print(val)
    
    # ######################## 字符串转成datetime ##############################
    # v1 = datetime.strptime('2011-11-11','%Y-%m-%d')
    # print(v1,type(v1))
    
    # ######################## datetime时间的加减 ##############################
    # v1 = datetime.strptime('2011-11-11','%Y-%m-%d')
    # v2 = v1 - timedelta(days=140)
    # date = v2.strftime('%Y-%m-%d')
    # print(date)
    
    # ######################## 时间戳和datetime关系 ##############################
    # ctime = time.time()
    # print(ctime)
    # v1 = datetime.fromtimestamp(ctime)
    # print(v1)
    
    # v1 = datetime.now()
    # val = v1.timestamp()
    # print(val)

7-1-7. 6.1.7 hashlib

  • 将指定的 “字符串” 进行加密。
import hashlib

def get_md5(data):
    obj = hashlib.md5()
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result

val = get_md5('123')
print(val)

​ 加严

import hashlib

def get_md5(data):
    obj = hashlib.md5("sidrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8'))
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result

val = get_md5('123')
print(val)

应用:

import hashlib
USER_LIST = []
def get_md5(data):
    obj = hashlib.md5("12:;idrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".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('登录失败')

7-1-8. 6.1.8 getpass

import getpass
#密码不显示(只能在终端运行)
pwd = getpass.getpass('请输入密码:')
if pwd == '123':
    print('输入正确')

7-1-9. 6.1.9 random

import random # 导入一个模块 

v = random.randint(起始,终止) # 获得一个随机数

7-1-10. 6.1.10 functools

-functools.reduce(func,v1)

7-2. 6.2 自定义模块

定义模块时能够把一个py文件或一个文件夹(包)看成一个模块,以方便于之后其余py文件的调用。

对于包的定义:

  • py2:文件见中必须有 _ _init _ _.py 。
  • py3:不须要 _ init _.py .

推荐你们之后写代码时,都要加上此文件。

导入模块方法:

  • import 模块 模块.函数()
  • from 模块 import 函数 函数() 【as起别名 / *表示所有】
  • from 模块 import 函数 as 别名 别名()
- 模块和要执行的py文件在同一目录 且 须要 模块中的不少功能时,推荐用: import 模块	模块.函数()
- 其余推荐:from 模块 import 模块       模块.函数()
- 其余推荐:from 模块.模块 import 函数   函数() 

1555575703809

1553910245673

7-3. 6.3 第三方模块

  • requests
  • xlrd

7-4. 6.4 异常处理

try:
    val = input('请输入数字:')
    num = int(val)
except Exception as e:
    print('操做异常')
# import requests
#
# try:
#     ret = requests.get('http://www.google.com')
#     print(ret.text)
# except Exception as e:
#     print('请求异常')
def func(a):
    try:
        return a.strip()
    except Exception as e:
        pass
    return False

v = func('alex')
if not v:
    print('函数执行失败')
else:
    print('结果是',v)
# 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 

def func2(url_list):
    result = []
    for url in url_list:
        try:
            response = requests.get(url)
            result.append(response.text)
        except Exception as e:
            pass
    return result 

func(['http://www.baidu.com','http://www.google.com','http://www.bing.com'])

7-5. 6.5 正则表达式

到底什么是正则表达式(regex)?

在编写处理字符串的程序或网页时,常常有查找符合某些复杂规则的字符串的须要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

在线工具

7-5-1. 6.5.1 经常使用元字符

\d	表示全部的数字
\w	字母/数字/下划线
\s	空白(空格/换行符/制表符)
\t	匹配制表符 Tab
\n	匹配换行符
.	表示除了换行符以外的任意内容
\D	表示全部的非数字
\W	表示除 数字字母下划线以外的全部字符
\S	表示非空白
[]	  	字符组 :只要在中括号内的全部字符都是符合规则的字符
[^xyz]	非字符组 :只要在中括号内的全部字符都是不符合规则的字符
^	表示一个字符的开始
$	表示一个字符的结束
|	表示或,注意,若是两个规则有重叠部分,老是长的在前面,短的在后面
()	表示分组,给一部分正则规定为一组,|这个符号的做用域就能够缩小了

[\d\D] [\W\w] [\S\s] 匹配全部一切字符

7-5-2. 6.5.2 经常使用限定符(量词)

代码/语法 说明
* 重复零次或更屡次
+ 重复一次或更屡次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更屡次
{n,m} 重复n到m次
> 匹配一个整数或者小数 \d+.\d+ \d+ \d+.?\d* \d+(.\d+)?
# 以a开头,由至少一个字母组成的字符串
# ^a[a-zA-Z]+
# ^a[a-zA-Z]*

# 以1开头,中间3-5个数字,若是中间位置超过5个数字,则整个字符串不匹配
# ^1\d{3,5}$

7-5-3. 6.5.3 贪婪匹配

默认采用回溯算法,贪婪匹配,老是会在符合量词条件的范围内尽可能多匹配.

adljdkjsljdlj

<.+> 会匹配到整个字符串,而不是

惰性匹配

老是匹配符合条件范围内尽可能小的字符串

格式: 元字符 量词 ? x

表示按照元字符规则在量词范围内匹配,一旦遇到x就中止

# 身份证号
# 15位  全数字 首位不为0
# 18位  前17位全数字 首位不为0  最后一位多是x和数字
# [1-9](\d{14}|\d{16}(\d|x))
# [1-9](\d{16}[\dx]|\d{14})
# [1-9]\d{14}(\d{2}[\dx])?

7-5-4. 6.5.4 表达式中转义符

正则表达式中的转义符在python的字符串中也恰好有转义的做用,可是正则表达式中的转义符和字符串中的转义符并不要紧,且还容易有冲突,为了不这种冲突,咱们全部的正则都以在工具中的测试结果为结果,而后只须要在正则和待匹配的字符串外面都加r便可.

  • \d \s \w \t \n→python字符串中
  • 匹配()[]{}\d等,须要加\转义

7-5-5. 6.5.5 ret正则模块

  • ret.findall('正则表达式',字符串)
    匹配字符串中全部符合规则的项,并返回一个列表,若是未匹配到返回空列表

  • ret.search('正则表达式',字符串)

    匹配字符串中知足条件的第一项,返回一个对象,用group方法取值;若是不能匹配上返回None,group方法会报错.

if ret:
    print(ret.group()) # 若是是对象,那么这个对象内部实现了group,因此能够取值
                       # 若是是None,那么这个对象不可能实现了group方法,因此报错
  • ret.match('正则表达式',字符串)

    会从头匹配字符串中取出从第一个字符开始是否符合规则,若是符合,就返回对象,用group取值,若是不符合,就返回None

    match = search + ^正则

  • re.finditer('正则表达式',字符串)

    返回一个迭代器,迭代出来的每一项都是一个对象,而后group取值

    在查询的结果超过1个的状况下,可以有效的节省内存,下降空间复杂度,从而也下降了时间复杂度

  • re.compile('正则表达式')

    正则表达式编译成python语言,供屡次使用

    ret = re.compile('\d3')
    r1=ret.search("djasjd5a646")
  • re.split()

    re.split('\d\d','alex83wusir74taibai')	  #不保存被分割的内容 [,1]第几个分割
    re.split('\d(\d)','alex83wusir74taibai')  # 默认自动保留分组中的内容
  • re.sub('正则表达式',替换内容,字符串,[序号])
    返回字符串

  • re.subn('正则表达式',替换内容,字符串,[序号])
    返回元组(替换后字符串,替换个数)

7-5-6. 6.5.6 分组

  • 分组命名
    (?P<组名>正则)

  • 引用分组
    (?P=组命)

  • findall和分组

    • 优先显示分组中的内容,其余内容内容返回空字符串""
    • (?:)取消这个分组的优先⭐ ,量词为了约定多个字符加括号,会产生此状况.
    import re
    ret = re.findall('\d+(\.\d+)?','21.234+2')
    print(ret)
    #运行结果:['.234', '']
    import re
    ret = re.findall('\d+(?:\.\d+)?','21.234+2')
    print(ret)
    #运行结果:['21.234', '2']

小技巧:有的时候咱们想匹配的内容包含在不相匹配的内容当中,这个时候只须要把不想匹配的先匹配出来,再经过手段去掉.

import re
ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret)
ret.remove('')
print(ret)
#运行结果:
#['1', '2', '60', '', '5', '4', '3']
#['1', '2', '60', '5', '4', '3']
  • split和分组
    会保留分组中原本应该被切割掉的内容
  • search和分组
    经过索引取 obj.group(1)
    经过组名取 obj.group('组名')
# 1.找出<h1>123fh</h1><h2>hado</h2>中全部标签内的字符串   爬虫
import re
ret = re.findall('<.*?>(.*?)<.*?>','<h1>123fh</h1><h2>hado</h2>')
print(ret)

# 2.找出四则运算表达式中的第一个乘除法
# \d*\d|\d/\d
# \d+(\.\d+)?[*/]\d(\.\d+)?
# \d+(\.\d+)?[*/]-?\d(\.\d+)?
import re
ret = re.search('\d+(\.\d+)?[*/]-?\d(\.\d+)?', '2-3*-5/6')
print(ret.group())

# 3.检测用户输入的内容是不是一个合法的身份证号     网页的合法输入(手机号码 qq号码 银行卡号 邮箱地址)
# '^[1-9]\d{14}(\d{2}[\dx])?$'
import re
inp = input('>>>').strip()
re.match('[1-9]\d{14}(\d{2}[\dx])?$', inp)  # 首选
re.search('^[1-9]\d{14}(\d{2}[\dx])?$', inp)
re.findall('^[1-9]\d{14}(\d{2}[\dx])?$', inp)
ret=re.findall(pattern,info,re.S) #容许.匹配下一行

8. 第七章 面向对象

8-1. 7.1 面向对象基本格式

# ###### 定义类 ######

class 类名:
    def 方法名(self,name):
        print(name)
        return 123

# ###### 调用类中的方法 ###### 
# 1.建立该类的对象
obj = 类名()
# 2.经过对象调用方法
result = obj.方法名('alex')
print(result)
# 若是在python2中这样定义,则称其为:经典类
class Foo:
    pass 
# 若是在python2中这样定义,则称其为:新式类
class Foo(object):
    pass 
# 在python3中这俩的写法是同样,由于全部的类默认都会继承object类,所有都是新式类。
class Base(object):
    pass
class Bar(Base):
    pass

8-2. 7.2 面向对象的特性

封装,继承,多态.

8-2-1. 7.2.1封装

  • 表现一:函数封装到类
class File:
    def read(self):
        pass
    def write(self):
        pass
  • 表现二:数据封装到对象 *
class Person:
    def __init__(sef,name,age):
        self.name = name
        self.age = age
p = Person('alex',19)

对象的做用:存储一些值,方便之后调用.

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('李兆琪',19,'男')
p1.show()

p2 = Person('利奇航',19,'男')
p2.show()

若是写代码时,函数比较多比较乱。

  1. 能够将函数归类并放到同一个类中。
  2. 函数若是有一个反复使用的公共值,则能够放到对象中。
class Person:
    def __init__(self,user,pwd,email):
        self.username = user
        self.password = pwd
        self.email = email
        


    def info(self):
        return "个人名字:%s,密码:%s,邮箱%s" %(self.username,self.password,self.email,)

USER_LIST = []#对象(用户/密码/邮箱),对象(用户/密码/邮箱),对象(用户/密码/邮箱)
while True:
    user = input('请输入用户名:')
    pwd = input('请输入密码:')
    email = input('请输入邮箱:')
    p = Person(user,pwd,email)
    USER_LIST.append(p)

for item in USER_LIST:
    msg = item.info()
    print(msg)

8-2-2. 7.2.2 继承

# 父类(基类)
class Base:
    def f1(self):
        pass
# 子类(派生类)
class Foo(Base):
    def f2(self):
        pass

# 建立了一个字类的对象
obj = Foo()
# 执行对象.方法时,优先在本身的类中找,若是没有就是父类中找。
obj.f2()
obj.f1()

# 建立了一个父类的对象
obj = Base()
obj.f1()

何时才能用到继承?多个类中若是有公共的方法,能够放到基类中避免重复编写。

class Base:
    def f1(self):
        self.f2()
        print('base.f1')
    def f2(self):
        print('base.f2')
class Foo(Base):
    def f2(self):
        print('foo.f2')
obj = Foo()
obj.f1()        
#foo.f2
#base.f1  注意self是谁

注意事项:

  • self 究竟是谁?
  • self 是哪一个类建立的,就今后类开始找,本身没有就找父类。

8-2-3. 7.2.3 多态-鸭子模型

# Python
def func(arg):
    v = arg[-1] # arg.append(9)
    print(v)

# java
def func(str arg):
    v = arg[-1]
    print(v)

什么是鸭子模型?

对于一个函数而言,Python对于参数的类型不会限制,那么传入参数时就能够是各类类型,在函数中若是有例如:arg.send方法,那么就是对于传入类型的一个限制(类型必须有send方法)。
这就是鸭子模型,相似于上述的函数咱们认为只要能呱呱叫的就是鸭子(只有有send方法,就是咱们要想的类型)

8-3. 7.3 成员

    • 类变量
    • 方法
      • 绑定方法
      • 类方法
      • 静态方法
    • 属性
  • 实例(对象)
    • 实例变量

8-3-1. 7.3.1 实例变量

实例本身封装的变量

class Foo:
    def __init__(self,name):
        self.name=name
        
     def info(self):
        pass
 obj1 = Foo("alex")
 obj2 = Foo('eric')

8-3-2. 7.3.2 类变量

  • 定义:写在类的下一级和方法同一级。

  • 访问:

    类.类变量名称 (推荐)
    对象.类变量名称
  • 面试题

    class Base:
        x = 1
        
    obj = Base()
    
    
    print(obj.x) # 先去对象中找,没有再去类中找。
    obj.y = 123  # 在对象中添加了一个y=123的变量。
    print(obj.y)
    obj.x = 123
    print(obj.x)
    print(Base.x)

    总结:找变量优先找本身,本身没有找 类 或 基类;修改或赋值只能在本身的内部设置。

8-3-3. 7.3.3 绑定方法/普通方法

  • 定义:至少有一个self参数
  • 执行:先建立对象,由对象.方法()。
class Foo:
    def func(self,a,b):
        print(a,b)
        
obj = Foo()
obj.func(1,2)
# ###########################
class Foo:
    def __init__(self):
        self.name = 123

    def func(self, a, b):
        print(self.name, a, b)

obj = Foo()
obj.func(1, 2)

8-3-4. 7.3.4 静态方法

  • 定义:
    • @staticmethod装饰器
    • 参数无限制
  • 执行:
    • 类.静态方法名 ()
    • 对象.静态方法() (不推荐)
class Foo:
    def __init__(self):
        self.name = 123

    def func(self, a, b):
        print(self.name, a, b)

    @staticmethod
    def f1():
        print(123)

obj = Foo()
obj.func(1, 2)

Foo.f1()
obj.f1() # 不推荐

8-3-5. 7.3.5 类方法

  • 定义:
    • @classmethod装饰器
    • 至少有cls参数,当前类。
  • 执行:
    • 类.类方法()
    • 对象.类方法() (不推荐)
class Foo:
    def __init__(self):
        self.name = 123

    def func(self, a, b):
        print(self.name, a, b)

    @staticmethod
    def f1():
        print(123)

    @classmethod
    def f2(cls,a,b):
        print('cls是当前类',cls)
        print(a,b)

obj = Foo()
obj.func(1, 2)

Foo.f1()
Foo.f2(1,2)
# 问题: @classmethod和@staticmethod的区别?
"""
一个是类方法一个静态方法。 
定义:
	类方法:用@classmethod作装饰器且至少有一个cls参数。
	静态方法:用staticmethod作装饰器且参数无限制。
调用:
	类.方法直接调用。
	对象.方法也能够调用。 
"""

8-3-6. 7.3.6 属性

  • 定义:
    • @property装饰器
    • 只有一个self参数
  • 执行:
    • 对象.方法 不用加括号。
class Foo:

    @property
    def func(self):
        print(123)
        return 666

obj = Foo()
result = obj.func
print(result)
# 属性的应用

class Page:
    def __init__(self, total_count, current_page, per_page_count=10):
        self.total_count = total_count
        self.per_page_count = per_page_count
        self.current_page = current_page
    @property
    def start_index(self):
        return (self.current_page - 1) * self.per_page_count
    @property
    def end_index(self):
        return self.current_page * self.per_page_count


USER_LIST = []
for i in range(321):
    USER_LIST.append('alex-%s' % (i,))

# 请实现分页展现:
current_page = int(input('请输入要查看的页码:'))
p = Page(321, current_page)
data_list = USER_LIST[p.start_index:p.end_index]
for item in data_list:
    print(item)

8-4. 7.4 成员修饰符

  • 公有,全部地方都能访问到。
  • 私有,只有本身能够访问到。
class Foo:
    def __init__(self, name):
        self.__name = name

    def func(self):
        print(self.__name)


obj = Foo('alex')
# print(obj.__name)
obj.func()
class Foo:
    __x = 1

    @staticmethod
    def func():
        print(Foo.__x)


# print(Foo.__x)
Foo.func()
class Foo:

    def __fun(self):
        print('msg')

    def show(self):
        self.__fun()

obj = Foo()
# obj.__fun()
obj.show()
# 强制访问私有成员

class Foo:
    def __init__(self,name):
        self.__x = name


obj = Foo('alex')

print(obj._Foo__x) # 强制访问私有实例变量

8-5. 7.4 嵌套

嵌套表现形式:

  • 函数: 参数能够是任意类型
  • 字典: 对象和类均可以作字典的key和value
  • 继承的查找关系
class StarkConfig(object):
    pass

class AdminSite(object):
    def __init__(self):
        self.data_list = []
        
    def register(self,arg):
        self.data_list.append(arg)
        
site = AdminSite()

obj = StarkConfig()
site.register(obj)	#将对象嵌入另外一类的对象的列表中
class StarkConfig(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

class AdminSite(object):
    def __init__(self):
        self.data_list = []
        self.sk = None

    def set_sk(self,arg):
        self.sk = arg
        
        
site = AdminSite() # data_list = []  sk = StarkConfig
site.set_sk(StarkConfig)
site.sk('alex',19)	#StarkConfig('alex',19)

8-6. 7.5 特殊成员

8-6-1. 7.5.1 __init__

class Foo:
    """
    类是干啥的。。。。
    """
    def __init__(self,a1):
        """
        初始化方法
        :param a1: 
        """
        self.a1 = a1
        
obj = Foo('alex')

8-6-2. 7.5.2__new__

class Foo(object):
    def __init__(self):
        """
        用于给对象中赋值,初始化方法
        """
        self.x = 123
    def __new__(cls, *args, **kwargs):
        """
        用于建立空对象,构造方法
        :param args: 
        :param kwargs: 
        :return: 
        """
        return object.__new__(cls)

obj = Foo()

8-6-3. 7.5.3 __call__

class Foo(object):
    def __call__(self, *args, **kwargs):
        print('执行call方法')

# obj = Foo()
# obj()
Foo()()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from wsgiref.simple_server import make_server

def func(environ,start_response):
    start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
    return ['你好'.encode("utf-8")  ]

class Foo(object):

    def __call__(self, environ,start_response):
        start_response("200 OK", [('Content-Type', 'text/html; charset=utf-8')])
        return ['你<h1 style="color:red;">很差</h1>'.encode("utf-8")]


# 做用:写一个网站,用户只要来方法,就自动找到第三个参数并执行。
server = make_server('127.0.0.1', 8000, Foo())
server.serve_forever()

8-6-4. 7.5.4 __getitem__

class Foo(object):

    def __setitem__(self, key, value):
        pass

    def __getitem__(self, item):
        return item + 'uuu'

    def __delitem__(self, key):
        pass


obj1 = Foo()
obj1['k1'] = 123  # 内部会自动调用 __setitem__方法
val = obj1['xxx']  # 内部会自动调用 __getitem__方法
print(val)
del obj1['ttt']  # 内部会自动调用 __delitem__ 方法

8-6-5. 7.4.5 __str__

class Foo(object):

    def __setitem__(self, key, value):
        pass

    def __getitem__(self, item):
        return item + 'uuu'

    def __delitem__(self, key):
        pass


obj1 = Foo()
obj1['k1'] = 123  # 内部会自动调用 __setitem__方法
val = obj1['xxx']  # 内部会自动调用 __getitem__方法
print(val)
del obj1['ttt']  # 内部会自动调用 __delitem__ 方法
class User(object):
    def __init__(self,name,email):
        self.name = name
        self.email = email
    def __str__(self):
        return "%s %s" %(self.name,self.email,)
user_list = [User('二狗','2g@qq.com'),User('二蛋','2d@qq.com'),User('狗蛋','xx@qq.com')]
for item in user_list:
    print(item)

8-6-6. 7.4.6__dict__

class Foo(object):
    def __init__(self,name,age,email):
        self.name = name
        self.age = age
        self.email = email

obj = Foo('alex',19,'xxxx@qq.com')
print(obj)
print(obj.name)
print(obj.age)
print(obj.email)
val = obj.__dict__ # 去对象中找到全部变量并将其转换为字典
print(val)

8-6-7. 7.4.7 上下文管理

class Foo(object):
    def __enter__(self):
        self.x = open('a.txt',mode='a',encoding='utf-8')
        return self.x
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.x.close()

with Foo() as ff:
    ff.write('alex')
    ff.write('alex')
    ff.write('alex')
    ff.write('alex')
# class Context:
#     def __enter__(self):
#         print('进入')
#         return self
#
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         print('推出')
#
#     def do_something(self):
#         print('内部执行')
#
# with Context() as ctx:
#     print('内部执行')
#     ctx.do_something()


class Foo(object):
    def do_something(self):
        print('内部执行')

class Context:
    def __enter__(self):
        print('进入')
        return Foo()

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('推出')

with Context() as ctx:
    print('内部执行')
    ctx.do_something()
val = 5 + 8
print(val)

val = "alex" + "sb"
print(val)

class Foo(object):
    def __add__(self, other):
        return 123
    
obj1 = Foo()
obj2 = Foo()
val  = obj1 + obj2
print(val)

8-6-8. 7.4.8 对象相加

val = 5 + 8
print(val)

val = "alex" + "sb"
print(val)

class Foo(object):
    def __add__(self, other):
        return 123
    
obj1 = Foo()
obj2 = Foo()
val  = obj1 + obj2
print(val)

8-7. 7.5 内置函数(补充)

8-7-1. 7.5.1 type,查看类型

class Foo:
    pass

obj = Foo()

if type(obj) == Foo:
    print('obj是Foo类的对象')

8-7-2. 7.5.2 issubclass

class Base:
    pass

class Base1(Base):
    pass

class Foo(Base1):
    pass

class Bar:
    pass

print(issubclass(Bar,Base))
print(issubclass(Foo,Base))

8-7-3. 7.5.3 isinstance

class Base(object):
    pass

class Foo(Base):
    pass

obj = Foo()

print(isinstance(obj,Foo))  # 判断obj是不是Foo类或其基类的实例(对象)
print(isinstance(obj,Base)) # 判断obj是不是Foo类或其基类的实例(对象)

8-8. 7.6 super

class Base(object):
    def func(self):
        print('base.func')
        return 123


class Foo(Base):
    def func(self):
        v1 = super().func()
        print('foo.func',v1)

obj = Foo()
obj.func()
# super().func() 去父类中找func方法并执行
class Bar(object):
    def func(self):
        print('bar.func')
        return 123

class Base(Bar):
    pass

class Foo(Base):
    def func(self):
        v1 = super().func()
        print('foo.func',v1)

obj = Foo()
obj.func()
# super().func() 根据类的继承关系,按照顺序挨个找func方法并执行(找到第一个就不在找了)
class Base(object): # Base -> object
    def func(self):
        super().func()
        print('base.func')

class Bar(object):
    def func(self):
        print('bar.func')

class Foo(Base,Bar): # Foo -> Base -> Bar
    pass

obj = Foo()
obj.func()

# super().func() 根据self对象所属类的继承关系,按照顺序挨个找func方法并执行(找到第一个就不在找了)

8-9. 7.7 异常处理

8-9-1. 7.7.1 基本格式

try:
    pass
except Exception as e:
    pass
try:
    v = []
    v[11111] # IndexError
except ValueError as e:
    pass
except IndexError as e:
    pass
except Exception as e:
    print(e) # e是Exception类的对象,中有一个错误信息。
try:
    int('asdf')
except Exception as e:
    print(e) # e是Exception类的对象,中有一个错误信息。
finally:
    print('最后不管对错都会执行')
    
# #################### 特殊状况 #########################
def func():
    try:
        # v = 1
        # return 123
        int('asdf')
    except Exception as e:
        print(e) # e是Exception类的对象,中有一个错误信息。
        return 123
    finally:
        print('最后')

func()

8-9-2. 7.7.2 主动触发异常

try:
    int('123')
    raise Exception('阿萨大大是阿斯蒂') # 代码中主动抛出异常
except Exception as e:
    print(e)
def func():
    result = True
    try:
        with open('x.log',mode='r',encoding='utf-8') as f:
            data = f.read()
        if 'alex' not in data:
            raise Exception()
    except Exception as e:
        result = False
    return result

8-9-3. 7.7.3 自定义异常

class MyException(Exception):
    pass

try:
    raise MyException('asdf')
except MyException as e:
    print(e)
class MyException(Exception):
    def __init__(self,message):
        super().__init__()
        self.message = message

try:
    raise MyException('asdf')
except MyException as e:
    print(e.message)

8-10. 7.8 可迭代对象

表象:能够被for循环对象就能够称为是可迭代对象:字符串,列表,字典...

  • 如何让一个对象变成可迭代对象?

在类中实现__iter__方法且返回一个迭代器(生成器)

class Foo:
    def __iter__(self):
        return iter([1,2,3,4])

obj = Foo()


class Foo:
    def __iter__(self):
        yield 1
        yield 2
        yield 3

obj = Foo()

记住:只要能被for循环就是去看他内部的iter方法。

8-11. 7.9 约束

# 约束字类中必须写send方法,若是不写,则调用时候就报抛出 NotImplementedError 
class Interface(object):
    def send(self):
        raise NotImplementedError()
        
class Message(Interface):
    def send(self):
        print('发送短信')
        
class Email(Interface):
    def send(self):
        print('发送邮件')

8-12. 7.10反射

根据字符串的形式去某个对象中 操做 他的成员。

  • getattr(对象,"字符串") 根据字符串的形式去某个对象中 获取 对象的成员.

    class Foo(object):
        def __init__(self,name):
            self.name = name
    obj = Foo('alex')
    
    # 获取变量
    v1 = getattr(obj,'name')
    # 获取方法
    method_name = getattr(obj,'login')
    method_name()
  • hasattr(对象,'字符串') 根据字符串的形式去某个对象中判断是否有该成员。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from wsgiref.simple_server import make_server
    
    class View(object):
        def login(self):
            return '登录'
    
        def logout(self):
            return '等出'
    
        def index(self):
            return '首页'
    
    
    def func(environ,start_response):
        start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
        #
        obj = View()
        # 获取用户输入的URL
        method_name = environ.get('PATH_INFO').strip('/')
        if not hasattr(obj,method_name):
            return ["sdf".encode("utf-8"),]
        response = getattr(obj,method_name)()
        return [response.encode("utf-8")  ]
    
    # 做用:写一个网站,用户只要来方法,就自动找到第三个参数并执行。
    server = make_server('192.168.12.87', 8000, func)
    server.serve_forever()
  • setattr(对象,'变量','值') 根据字符串的形式去某个对象中设置成员。

    class Foo:
        pass
    
    
    obj = Foo()
    obj.k1 = 999
    setattr(obj,'k1',123) # obj.k1 = 123
    
    print(obj.k1)
  • delattr(对象,'变量') 根据字符串的形式去某个对象中删除成员。

    class Foo:
        pass
    
    obj = Foo()
    obj.k1 = 999
    delattr(obj,'k1')
    print(obj.k1)

python一切皆对象

  • py文件
  • 对象

python一切皆对象,因此之后想要经过字符串的形式操做其内部成员均可以经过反射的机制实现。

8-13. 7.11.单例模式

不管实例化多少次,永远用的都是第一次实例化出的对象。

class Foo:
    pass

# 多例,每实例化一次就建立一个新的对象。
obj1 = Foo() # 实例,对象
obj2 = Foo() # 实例,对象
# 单例,不管实例化多少次,都用第一次建立的那个对象。
obj1 = Foo()
obj2 = Foo()

单例模式标准

class Singleton(object):
    instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = object.__new__(cls)
        return cls.instance

obj1 = Singleton()
obj2 = Singleton()

# 不是最终,加锁。

文件的链接池

class FileHelper(object):
    instance = None
    def __init__(self, path):
        self.file_object = open(path,mode='r',encoding='utf-8')

    def __new__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = object.__new__(cls)
        return cls.instance

obj1 = FileHelper('x')
obj2 = FileHelper('x')
  • 模块屡次导入从新加载
import jd # 第一次加载:会加载一遍jd中全部的内容。
import jd # 由已经加载过,就不在加载。
print(456)
import importlib
import jd
importlib.reload(jd)
print(456)

经过模块导入的特性也能够实现单例模式:

# jd.py
class Foo(object):
    pass

obj = Foo()
# app.py
import jd # 加载jd.py,加载最后会实例化一个Foo对象并赋值给obj
print(jd.obj)

8-14. 7.12日志

  • logging基本应用

  • 日志处理本质:Logger/FileHandler/Formatter

  • 推荐处理日志方式

    import logging
    
    file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[file_handler,],
        level=logging.ERROR
    )
    
    logging.error('你好')
  • 推荐处理日志方式 + 日志分割

    import time
    import logging
    from logging import handlers
    # file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    file_handler = handlers.TimedRotatingFileHandler(filename='x3.log', when='s', interval=5, encoding='utf-8')
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[file_handler,],
        level=logging.ERROR
    )
    
    for i in range(1,100000):
        time.sleep(1)
        logging.error(str(i))

    注意事项:

    # 在应用日志时,若是想要保留异常的堆栈信息。
    import logging
    import requests
    
    logging.basicConfig(
        filename='wf.log',
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        level=logging.ERROR
    )
    
    try:
        requests.get('http://www.xxx.com')
    except Exception as e:
        msg = str(e) # 调用e.__str__方法
        logging.error(msg,exc_info=True)

8-15. 7.13项目结构目录

1556459318540

1556459350241

1556459398316

9. 第八章 网络编程

10. 第九章 并发编程

11. 第十章 数据库

12. 第十一章 前端开发

13. 第十二章 Django框架

14. 附录 常见错误和单词

14-1. py2&py3区别

  • py2:
    xrange,不会在内存中当即建立,而是在循环时。边循环边建立。
    range ,在内存当即把全部的值都建立。
    py3:
    range ,不会在内存中当即建立,而是在循环时。边循环边建立。
    list(range(10))

14-2. 单词

upper 大写 ...

14-3. 错误记录

14-3-1.

14-4. 面试题

  • 线上操做系统:centos

  • py2和py3的区别?

  • 每种数据类型,列举你了解的方法。

  • 3 or 9 and 8

  • 字符串的反转

  • is 和 == 的区别?

  • v1 = (1) / v2 = 1

  • 深浅拷贝

  • 文件操做,大文件如何读取内容 [ 50G的日志文件 ]

    v = open(....)
    
    for line in v:
        print(line)
        
    v.close()
  • 一行写出:9*9乘法表【不会】

  • git流程【不会】

  • global和nonlocal区别

  • 需求分析

  • 诚实

  • 知识边界分析,对比