Particles

Python基础学习

1.Python的基本数据类型:

1、int(整数),主要用来进行数学运算,(不可迭代)
2、str(字符串) (可迭代)
3、bool(布尔值) 判断真假 true false
4、list(列表) 存储大量数据 用[]表示 (可迭代)
5、tuple(元组),不可以发生改变 (5可迭代)
6、dict(字典),保存键值对,可以保存大量的数据,无序
7、set(集合),保持大量数据,不可以重复

1.基础数据类型总结

有序无序 是否可变 是否迭代 取值方式
int 有序(不支持索引) 不可变(可哈希) 不可迭代 直接查看
bool 不可变(可哈希) 不可迭代 直接查看
str 有序(支持索引) 不可变(可哈希) 可迭代 通过索引查看
tuple 有序(支持索引) 不可变(可哈希) 可迭代 通过索引查看
list 有序(支持索引) 可变(不可哈希) 可迭代 通过索引查看
dict 无序(不支持索引) 可变(不可哈希) 可迭代 通过键查看
set 无序(不支持索引) 可变(不可哈希) 可迭代 直接查看

##注意事项

  • 列表和元组进行乘法时元素都是共用的

    lst = (1,2,[])
    lst1 = lst * 2
    lst1[-1].append(8)
    print(lst)
    print(lst1)
    >>>(1, 2, [8]) (1, 2, [8], 1, 2, [8])
    
  • 字典和集合

    • 大小说的是字典的长度,长度就是键值的个数
    • 不能修改键值对的大小,但能修改键对应的值
  • 集合

    • 大小说的是集合的长度,长度就是元素的个数

2.字符串

  • 字符串在+和*时都是新开辟地址

3.元组

  • V1 = (11, 22, 33) ###tuple

  • 数据类型之一,支持索引,支持切片

  • 元组是一个有序、可迭代、不可变的数据类型

  • 元组 v1 = (11,22,33) ---->叫元组,元组里的一个个值叫元素,以逗号分隔

  • 元组不能增删改,只能查

  • ()括号中如果只有一个元素,并且没有逗号,那么它不是元组,它与该元素的数据类型一致。

  • 长度说的是元素的个数

    v1 = (11, 11, 22, 33)
    print(v1.count(33)) >>>>1 
    print(v1.count(11)) >>>>2
    ###统计元素的个数
    print(v1.index(33)) >>>>3
    ###通过元素的名称获取元素的索引
    
    
  • 面试题

     # a = (10)  
     print(type(a))  >>><class 'tuple'> #当小括号中没有逗号时,数据类型就是括号中数据类型本身
     # a = ("alex")
     print(type(a))  >>><class 'str'> #当小括号中没有逗号时,数据类型就是括号中数据类型本身
     # a = ("alex",)
     print(type(a)) >>><class 'tuple'> #这是一个元组
     # a = ()
     print(type(a)) >>><class 'tuple'> #这是元组    
     # a = (1,2,3)
     print(type(a)) >>><class 'tuple'> #这是元组    
    

4.列表

  • V1 = [11, 22, 33] 以逗号分隔每一个内容为元素
  • 列表就是一容器
  • 可以存储大量不同数据类型的数据
  • 列表可以增删改查
  • 列表是可变数据类型,可迭代数据类型,有序数据结构
  • 列表在进行乘法时,元素都是共用的

##增

​ +

lis = [1,2,3]
lst1 = [4,5,6]
print((lis + lst1))
>>>>[1, 2, 3, 4, 5, 6]

​ *

lst = [1,2,3]
print(lst * 5)
>>>>[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

​ append 追加

lst = ["Python学习手册", "核心编程"]
lst.append("流畅的Python")
print(lst)
>>>>['Python学习手册', '核心编程', '流畅的Python']

​ insert 按照索引插入

lst = ["Python学习手册", "核心编程"]
lst.insert(0, "Python的学习手册2")
print(lst)
>>>>['Python的学习手册2', 'Python学习手册', '核心编程']

​ extend 迭代着追加

lst = ["Python学习手册", "核心编程"]
lst.extend(["老男孩"])
print(lst) >>>>['Python学习手册', '核心编程', '老男孩']
lst.extend("老男孩")
print(lst) >>>>['Python学习手册', '核心编程', '老男孩', '老', '男', '孩']

##删

​ pop 按照索引位置删除,默认删除列表中最后一位元素,并且有返回值,返回被删除的元素

lst = ["傻屌1", "笨蛋1", "傻狗1"]
lst.pop(1)
print(lst)
>>>>['傻屌1', '傻狗1']

​ remove 指定元素删除,如果有重名元素,默认删除从左数第一个

lst = ["傻屌1", "笨蛋1", "傻狗1"]
lst.remove("傻屌1")
print(lst)
>>>>['笨蛋1', '傻狗1']

​ clear 清空整个列表,不能指定

lst = ["傻屌1", "笨蛋1", "傻狗1"]
lst.clear()
print(lst)
>>>>[]

​ del 删除整个列表,也可按照索引删除 del l1[-1]

lst = ["傻屌1", "笨蛋1", "傻狗1"]
del lst
print(lst)
>>>>>NameError: name 'lst' is not defined
del lst[2]
print(lst)
>>>>['傻屌1', '笨蛋1']

###for循环删除

lst = [11,22,33,44,55]
for循环

####投机取巧
for i in lst:
    lst.clear()
print(lst)

####方式一:
for i in range(len(lst)):
    lst.pop(0)
print(lst)

for i in range(len(lst)):
    lst.pop()
print(lst)

####方式二:
lst = [11,22,33,44,55]
lst1 = lst.copy()
for i in lst1:
    lst.remove(i)
print(lst)

##改

  • 按照索引进行改值
lst = ["傻屌1", "笨蛋1", "傻狗1"]
lst[2] = "傻帽1"
print(lst)
>>>>['傻屌1', '笨蛋1', '傻帽1']
  • 按照切片进行改值
    • 必须是可迭代数据,步长为1时,修改的内容可多可少
lst = ["傻屌1", "笨蛋1", "傻狗1", "哈皮1"]
lst[1:3] = "杀鬼", "鸟蛋", "狗屎"
print(lst)
>>>>['傻屌1', '杀鬼', '鸟蛋', '狗屎', '哈皮1']
lst[0:3] = "杀鬼鸟蛋狗屎"
>>>>['杀', '鬼', '鸟', '蛋', '狗', '屎', '哈皮1']
#######################################################################	
l1 = [44, 55, 66]
l1[2:] = "f","s","asdasd","asdasdasdasd"
>>>>[44, 55, 'f', 's', 'asdasd', 'asdasdasdasd']
  • 按照切片(步长)进行改值,所谓的隔值进行更改
    • 必须是可迭代数据,步长不为1时,修改的内容得一一对应
lst = ["傻屌1", "笨蛋1", "傻狗1", "哈皮1","山药","鬼"]
lst[0:4:2] = [ "狗屎","朱"]
print(lst)
>>>>['狗屎', '笨蛋1', '朱', '哈皮1', '山药', '鬼']
lst[1:3:2] = [ "狗屎"]
>>>>['傻屌1', '狗屎', '傻狗1', '哈皮1', '山药', '鬼']
lst[1:4:2] = [ "狗屎","猪"]
>>>>['傻屌1', '狗屎', '傻狗1', '猪', '山药', '鬼']
  • 反向列表中的元素

    lst = [1,2,3,4,6,5]
    lst.reverse()                 # 原地修改
    print(lst)
    >>>>[5, 6, 4, 3, 2, 1]
    
    • 排序
    lst = [1,2,3,4,6,5]
    lst.sort()                      # 排序 默认是升序
    print(lst)
    >>>>[1, 2, 3, 4, 5, 6]
    
    
    • 降序
    lst = [1,2,3,4,6,5]
    lst.sort(reverse=True)            # 降序
    print(lst)
    >>>[6, 5, 4, 3, 2, 1]
    

##查

​ 按照索引进行查找(索引正序从0开始,倒序从-1开始)

l1 = [44, 55, 66, 22, 22]
print(l1[1])  
>>>>55

​ 安装切片进行查找

l1 = [44, 55, 66, 22, 22]
print(l1[0:3])
>>>[44, 55, 66]
例子:
li = [1, 3, 2, "a", 4, "b", 5, "c"] 
print(li[0:3]) >>>>[1, 3, 2]
print(li[1:7:2]) >>>>[3, 'a', 'b']
print(li[-3:-8:-2]) >>>>['b', 'a', 3]

#列表嵌套

lst = ["傻屌1", ["笨蛋1","笨蛋2", ["傻狗1", "傻狗2"],"哈皮1"],"山药","鬼"]
print(lst[1][2][1])
>>>>傻狗2

5.while循环

  • break #跳出当前循环,while循环遇到break直接退出不再循环
  • continue #跳出本次循环,继续下次循环(continue就是所在循环体的最后一行代码,循环遇到continue相当于执行到循环底部)
  • 在循环体中当遇到break或continue,那么此循环体中break或continue下方的代码都不会被执行
  • while...else语句,while如果被break打断,则不执行else语句

6.if循环

  • 单if

  • if...else...

  • if...elif...elif...elif

  • if...elif...elif...else

  • if嵌套

  • if...if...if

  • 例子

    # num = input("儿子,让爸爸看看你考了多少分:")
    # if int(num) >= 90:
    #     print("A")
    # elif int(num) >= 80 and int(num) < 90:
    #     print("B")
    # elif int(num) >= 70 and int(num) < 80:
    #     print("C")
    # else:
    #     print("太笨了,不像我,呼伦贝尔大草原呀")
    
  • 三元运算

    num = input("请输入你喜欢的数字:")                  
    s = 0                                      
    if int(num) > 0:                           
        for i in num:                          
            s = s + int(i) ** 3                
        # print(s)    
    ###三木
    print("是水仙花" if s == int(num) else "不是")   
    

7.for循环

  • for循环结构

    # for i  in  xxx:
    # for 关键字
    # i 变量名
    # in  关键字
    # xxx 可迭代对象
    
  • 例子:

    name = "alex"
    for i in name:
         print(i)
    
    a
    l
    e
    x
    
  • for i in "":  ###为空
        print(i)
    ###不会执行
    

8.编码

- ASCII	    最早的密码本,不支持中文。
		   #英文 一个字符占用8位
- GBK	    国标 
	       #英文 一个字符占用8位(1字节)
	       #中文 一个字符占用16位(2字节)
- Unicode   万国码   兼容性高
		   #英文  32位(4字节)
		   #中文  32位(4字节)
- UTF-8		Unicode的升级版本
		   #英文  8位(1字节)
		   #欧洲  16位(2字节)
		   #亚洲  24位(3字节)
  • 单位转换:

    1byte = 8bit
    1kb = 1024byte
    1mb = 1024kb
    
  • 在内存中所有的编码必须是unicode存在,除去bytes

#bytes

  • bytes类型存在的意义:

    因为Python字符串类型为str,在内存中用Unicode表示,但是在网络传输过程中或者要存入磁盘时,就需要将str转换成以字节为单位的bytes类型

9.str取值

安装索引:s1[index]
按照切片:s1[start_index:end_index+1]
按照切片步长:s1[start_index:end_index+1:2]
反向按照切片步长:s1[start_index:end_index后延一会:2]

10.哈希数据类型

  • 不可变数据类型(可哈希):int str tuple bool
  • 可变(不可哈希)的数据类型:list dict set

11.解构

  • 一行代码进行数值交换
a = 10
b = 20
a, b = b, a
print(a)   >>>>>20
print(b)   >>>>>10


a ,b ,c, d, f = (1, 2, 3, 4, 5)
print(a, b, c, d, f)
>>>>1 2 3 4 5

a ,b ,c, d, *f = (1, 2, 3, 4, 5, 6, 7, 8)
print(a, b, c, d, f)
>>>>>1 2 3 4 [5, 6, 7, 8]

12.字典

  • info =

    k1和k2叫键(keys) v1和v2叫值(values )

  • 键:必须是不可变的数据类型(int,str,bool,tuple),唯一的

  • 值:任意数据类型,对象

  • 查找方便,查询速度快 ,可存储大量的关联型数据

  • 可变,无序,不支持索引

  • 例子:

    info = {'k1':'v2', 'k2': 'v2'}
    print(info.keys())  >>>>dict_keys(['k1', 'k2'])
    print(info.values()) >>>>dict_values(['v2', 'v2'])
      
    ############
    dic = {}
    print(dict(k=1,v=2,b=4))
    print(dict([(1,2),(4,5),(7,8)]))
    >>>
    {'k': 1, 'v': 2, 'b': 4}
    {1: 2, 4: 5, 7: 8}
    
    #####################
    locals = {'沪':'上海', '⿊':'⿊⻰江', '鲁':'⼭东'}
    for i in locals:
        print(i)
    >>>>沪 黑  鲁
    

##批量创建键值对

  • fromkeys(seq,values)
    • 批量创建键值对,以序列 seq 中元素做字典的键,value 为字典所有键对应的初始值
dic = dict.fromkeys('abc', 100)
print(dic) >>>>{'a': 100, 'b': 100, 'c': 100}
dic1 = dict.fromkeys([1, 2, 3], "qwe")
print(dic1) >>>>{1: 'qwe', 2: 'qwe', 3: 'qwe'}
dic2 = dict.fromkeys([1, 2, 3], [])
print(dic2) >>>>{1: [], 2: [], 3: []}
dic3 = dict.fromkeys([1, 2, 3], [])
dic3[1].append(666)
print(dic3)>>>>{1: [666], 2: [666], 3: [666]}

##增

  • 通过键直接加
dic2 = {'na' : 'chen', 'age22' : '32'}
dic2["inttt"] = "lichen"
print(dic2)
>>>>{'na': 'chen', 'age22': '32', 'inttt': 'lichen'}
  • setdefault()
    • 如果键不已经存在于字典中,将会添加键并将值设为默认值None
dic2 = {'na' : 'chen', 'age22' : '32'}
dic2.setdefault('na',"18")
print(dic2)
>>>{'na' : 'chen', 'age22' : '32'}   ###字典中键存在时不添加,不存在时再进行

dic2.setdefault('na2')
print(dic2) 
>>>>{'na': 'chen', 'age22': '32', 'na2': None} ## 键不存在返回None

##删

  • 字典中没有remove
  • pop(),删除指定键值对
    • 有返回值,返回被删除的键对应的值
dic2 = {'na' : 'chen', 'age22' : '32'}
dic2.pop('na')
print(dic2)
>>>>{'age22': '32'}
  • clear()
    • 清空
  • popitem()
    • 随机删除,默认删除最后一个
dic2 = {'na' : 'chen', 'age22' : '32'}
dic2.popitem()
print(dic2)
>>>>{'na': 'chen'}
  • del
    • 删除整个字典
    • 可指定键进行删除
dic2 = {'na' : 'chen', 'age22' : '32'}
del dic2['na']
print(dic2)
>>>>{'age22': '32'}

###for循环删除字典中的键值对

dic = {"key":1,"key2":2}
dic1 = dic.copy()
for i in dic1:
    del dic[i]
print(dic)
>>>>{}

##改

  • 通过键直接改,键不存在时再增加
dic2 = {'na' : 'chen', 'age22' : '32'}
dic2['na'] = "chenhao"
print(dic2)
>>>>>>{'na': 'chenhao', 'age22': '32'}
dic2['name'] = "ALEX"
>>>>>>{'na': 'chen', 'age22': '32', 'name': 'ALEX'}
  • update
    • 增加键值对(有则更新,无则添加)
dic = {'na' : 'chli', 'age' : '18'}
dic2 = {'na' : 'chen', 'age22' : '32'}
dic.update(dic2) >>>>{'na': 'chen', 'age': '18', 'age22': '32'}
dic2.update(dic) >>>>{'na': 'chli', 'age22': '32', 'age': '18'}
dic.update(na = 'yyf',set = 'asdasd')  >>>>{'na': 'yyf', 'age': '18', 'set': 'asdasd'}
dic = {}
dic.update({"ysue" : "asd"})
print(dic) >>>{'ysue': 'asd'}

##查

  • 通过键直接查找,查不到会报错

    dic2 = {'na' : 'chen', 'age22' : '32'}
    print(dic2['na'])  >>>chen 通过键查找,查不到是报错
    
  • keys()

    • 获取字典索引的键
    dic2 = {'na' : 'chen', 'age22' : '32'}
    print(dic2.keys())
    >>>>dict_keys(['na', 'age22'])
    
  • values()

    • 获取字典所有的值
    dic2 = {'na' : 'chen', 'age22' : '32'}
    print(dic2.values())
    >>>>>dict_values(['chen', '32'])
    
  • setdefault()

    dic2 = {'na' : 'chen', 'age22' : '32'}
    print(dic2.setdefault('na'))
    >>>>chen
    
  • get()

    • 存在是返回值,不存在返回None
    dic2 = {'na' : 'chen', 'age22' : '32'}
    print(dic2.get('age22'))   >>>32
    print(dic2.get('name'))   >>>>None  键不存在时返回None
    
    • 通过键查找,若键存在,返回对应的值,若不存在,可指定返回内容
    dic2 = {'na' : 'chen', 'age22' : '32'}
    print(dic2.get('age22','没有找到'))  >>>>32
    print(dic2.get('name','没有找到'))   >>>>没有找到
    dic2["age22"] = dic2.get("age22") + 1
    print(dic2) >>{'na': 'chen', 'age22': 33}
    
    
    dic = {"A": {"c" : "稷山"}, "B": "唐山"}
    dic['A']['c'] = dic.get(dic['A']['c'], 1) +1
    print(dic)
    >>>>{'A': {'c': 2}, 'B': '唐山'}
    

##高仿列表

  • 可用于for循环
dic2 = {'na' : 'chen', 'age22' : '32'}
lst = dic2.keys()
print(lst)
>>>> ['na', 'age22']

##字典的嵌套

dic = {"1":"饺子",
       "2":"粥",
       "3":"面条",
       "4":"肉",
       "5":"土",
       "6":"东南风",
       "7":"切糕",
       "8":"烤全羊",
       "9":"烤骆驼",
       "10":"锅包肉",
       "11":"杀猪菜",
       "12":"乱炖"
       }
while True:
    choose = input("请输入月份:")
    if choose in dic:
        print(dic[choose])

13.运算符

##比较运算符

  • >   <   >=   <=   ==   !=
    

##算术运算符

  • + - * /(加减乘除)
    //(整除|底板除(向下取整))
    ** 幂
    % 取余 (模)
    #### print(5 / 2)  # 2.5
    #### print(5 // 2) # 2
    #### print(2 ** 0) # 1
    #### print(5 % 2)  # 1
    

##赋值运算符

  • ####     =
    ####     +=
    ####     -=
    ####     *=
    ####     /=
    ####     //=
    ####     **=
    ####     %= 
    ####     a = 10
    ####     b = 2
    ####     b += 1 # b = b + 1
    ####      a -= 1  # a = a - 1
    ####     a *= 2  # a = a * 2
    ####     a /= 2  # a = a / 2
    ####     a //= 2 # a = a // 2
    ####     a **= 2 # a = a ** 2
    ####     a %= 2  # a = a % 2
    

##逻辑运算符

  • and ## or ## not

  • 优先级:()> not > and > or

  • 查找顺序:从左到右

  • 练习

    # 3>2 and 4>2 or True and not False and True
    # 3>2 and 4>2 or True and True and True
    # True and True or True and True and True
    
  • Ture和False进行逻辑运算时:

    and:

    • 一真一假,就是假
    • 同真为真,同假为假

    or:

    • 一真一假就是真
    • 同真为真,同假为假
  • and数字进行逻辑运算时:

    • 数字不为0时和不为False,and运算选择and后面的内容
    • and运算都为假是选择and前的内容
    • and运算一真一假选择假
  • or数字进行逻辑运算时:

    • 数字不为0时和不为False,or运算选择or前面的内容
    • or运算都为假时选择or后面的内容
    • or运算一真一假选择真

##成员运算符

  • in(在)
  • not in(不在)
name = "alex"
msg = input(">>>")
if name in msg:
     print(111)
else:
     print(222)

14.格式化输出

#%s-%d-%i

name = input("name")
age = input("age")
msg = """
------info------
name:%s
age:%s
-------end------
"""
print(msg%(name,int(age),))
####此处的变量会按照位置来进行一一对应
  • %:占位符

  • %s字符串:%s可以填充字符串也可以添加数字

  • %d或i% 整型:必须填充数字

    name = int(input("请输入你喜欢的数字"))
    msg = '''
    NAME = %d
    '''
    print(msg%(name))
    
  • %%转义:变成普通的%

    num = int(input("请输入你喜欢的数字"))
    msg = '''
    NUM = 目前的学习进度是%d%%
    '''
    print(msg%(num))
    

#f-strings

F(f)+ str的形式,在字符串中想替换的位置用{}展位,与format类似,但是用在字符串后面写入替换的内容,而他可以直接识别

  msg = f'name:{input("name")},age:{input("age")}'
  print(msg)
  • 任意表达式

    • 字典
    lst = {'name' : 'chenhao_li' , 'age' :18}
    msg = f"我是{lst['name']},年龄{lst['age']}"
    print(msg)
    >>>>我是chenhao_li,年龄18
    
    • 列表
    lst = ['chenhao_li',18]
    msg = f"我是{lst[0]},年龄{lst[1]}"
    print(msg)
    >>>>我是chenhao_li,年龄18
    
  • 表达式

    • 用函数完成相应的功能
    def lst(a,b):
        return a + b
    a = 1
    b = 2
    print("相加为:" + f"{lst(a,b)}")
    >>>>相加为:3
    
  • 多行f输入

    name = 'barry'
    age = 18
    ajd = 'handsome'
    speaker = f'我叫{name}.'\
              f'You are {age} years old.'
    print(speaker)
    >>>>我叫barry.You are 18 years old.
    
  • if

    a = 10
    b = 20
    msg = f"{a if a < b else b}"
    print(msg)
    >>>>10
    
  • 其他

    print(f"{{73}}")  # {73}
    print(f"{{{73}}}")  # {73}
    print(f"{{{{73}}}}")  # {{73}}
    
    • !,:{};这些标点不能出现在{}里面,会报错

    • 使用lambda表达式会出现问题,可将lambda嵌套在圆括号里面解决问题

      x = 5
      print(f'{(lambda x: x*2) (x)}')  # 10
      

15.赋值与深浅copy

##赋值

  • 两个或多个变量名指向同一个内存地址,有一个操作内存地址的值进行改变,其余的变量名在查看的时候都进行更改

##浅copy

  • 只copy第一层的元素内存地址,可变的不可变的数据都是公用的

  • 多个变量指向同一个内存地址时,如果要修改的内存地址的数据是可变数据类型时,会在原地进行修改(列表、集合)。如果要修改的内存地址的数据是不可变数据类型时,是会重新开辟一个空间(字符串,数字)

    • 共用一个值(不同变量的地址指向同一个值)

    • 这两个变量指向值的内存地址一样

    • 可变数据类型:对其中一个变量的值改变,另外一个变量的值也会改变

    • 不可变数据类型:对其中一个的改变,另外一个不变

    • 不可变数据类型时

      lst1 = [1, 2, 3, [9, 8, 7], 4]
      lst2 = lst1[:]  #浅copy
      lst1.append(99)
      print(lst1,lst2)
      >>>>[1, 2, 3, [9, 8, 7], 4, 99] [1, 2, 3, [9, 8, 7], 4]
      
    • 可变数据类型时

      lst1 = [1, 2, 3, [9, 8, 7], 4]
      lst2 = lst1[:]
      lst1[-2].append(99)
      print(lst1,lst2)
      >>>>[1, 2, 3, [9, 8, 7, 99], 4] [1, 2, 3, [9, 8, 7, 99], 4]
      

##深copy

  • 对于不可变的数据,元素是共用的,可变的数据,开辟新的空间,不管嵌套多少层(copy完之后,彼此之间没关系,各过个的日子)

    • 两个变量的内存地址不同

    • 两个变量各有自己的值,且互不影响

    • 对其任意一个变量的值的改变不会影响另外一个

    • 不可变数据类型

      b = [1 ,2, 3, [99, 88, 77]]
      b1 = copy.deepcopy(b)
      b.append(44)
      print(b,b1)
      >>>>[1, 2, 3, [99, 88, 77], 44] [1, 2, 3, [99, 88, 77]]
      
    • 不可变数据类型

      b = [1 ,2, 3, [99, 88, 77], 22]
      b1 = copy.deepcopy(b)
      b[-2].append(44)
      print(b,b1)
    

##==

  • 判断等号两边的值是否相同
a = 10
b = 10
print(a == b)
>>>>Ture

##is

  • 判断两边的值的内存地址是否相同
a = 10
b = 10
print(a is b)
>>>>Ture

16.小数据池和代码块(驻留机制)

驻留机制------节省内存,提高效率

代码块的优先级高于小数据池

##代码块

  • 一个py文件、一个函数、一个模块、一个类、终端下的每一行
  • 数字:-5 ~ 正无穷
  • 所有的代码都是依赖代码块执行
  • 乘法时总长度不能超过20

##小数据池

  • 数字、字符串、布尔值
  • 数字:-5 ~ 256
  • 字符串
    • 定义和乘法时不能出现中文和特殊字符
    • 3.6版本乘法时总长度不能超过20
    • 3.7版本乘法总长度不能超过4096

17.集合

  • set =

  • 可以去重

    s5 = {1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6 }
    l1 = list(s5)
    print(l1)          ###>>> [1, 2, 3, 4, 5, 6]
    
  • 大小说的是集合的长度

##增

  • add 随意位置插入

    set = {'太白', '张三', '李四', '王五'}
    set.add('xx')
    print(set)
    >>>>{'张三', '李四', '王五', '太白', 'xx'}
    
    
  • update 随意位置按元素增加,并去除重复

    set = {'太白', '张三', '李四', '王五'}
    set.update('asdasdasd')
    print(set)
    >>>>{'李四', '王五', 'd', '张三', '太白', 's', 'a'}
    

##删

  • remove 指定元素进行删除

    set = {'太白', '张三', '李四', '王五'}
    set.remove('太白')
    print(set)
    >>>>{'李四', '王五', '张三'}
    
  • pop 例:set.pop() 随机删除,有返回值

    set = {'太白', '张三', '李四', '王五'}
    set.pop()
    print(set)
    >>>>{'张三', '李四', '太白'}
    
  • clear() 清空

    a = {1, 2, 3, 4, 5}
    a.clear()
    print(a)
    >>>>set()
    

##改

  • 先删除再添加

    a = {1, 2, 3, 4, 5}
    a.remove(2)
    a.add(333)
    print(a)
    >>>>{1, 3, 4, 5, 333}
    
  • 转换数据类型

    a = {1, 2, 3, 4, 5}
    b = list(a)
    b[2] = 33
    print(b)
    >>>>[1, 2, 33, 4, 5]
    

##查

  • for 循环

##交-并-差-反交-子-超

s1 = {1, 2, 3, 4, 5, 6}
s2 = {5, 6, 7, 8, 9, 10}
###交集
print(s1 & s2)     ###>>>{5, 6}
###并集
print(s1 | s2)     ###>>>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
###差集
print(s1 - s2)     ###>>>{1, 2, 3, 4}  #s1对比s2取独有的
print(s2 - s1)     ###>>>{8, 9, 10, 7} #s2对比s1取独有的
###反交集
print(s1 ^ s2)     ###>>>{1, 2, 3, 4, 7, 8, 9, 10}
###子集
s3 = {1, 2, 3}
s4 = {1, 2, 3, 4, 5}
print(s3 < s4)     ###>>>True
###超集
print(s3 > s4)     ###>>>False

18.文件操作

##文件操作模式

  • r 只读
  • w 清空写(可创建文件)
  • a 追加写(可创建文件)
  • rb 只读字节
  • wb 清空写字节
  • ab 追加写字节
  • r+ 读写
  • w+ 清空写读
  • a+ 追加写读

##文件操作步骤

f = open("文件名字或文件路径",mode="操作模式",encoding="编码")

##转义

  • "C:\user" 用两个 \ \ 转义一个 \
  • r"C:\user" 用 r 代表转义 (推荐使用)
f = open(r"C:\Python_26\day07\萝莉.txt",mode="r",encoding="utf-8")

##读操作( r , rb)

  • read() 全读
  • read(3) r 模式是三个字符,rb 模式是三个字节
  • readline() 读取一行,默认带一个\n
  • readlines() 读取所有,存储在列表中
  • for i in f: 文件句柄可以迭代,一行一行读取

##清空写( w , wb)

  • 有文件时清空文件,没文件时创建文件
  • 打开文件时清空文件内容
  • 写入内容
def lst(name,sex,age,work):
    mingdan = (f"姓名:{name},性别:{sex},年龄:{age},学历:{work}")
    with open("student_msg.txt","a",encoding="utf-8") as f:
        f.write("\n"+mingdan)
lst("lichenhao","nan",18,"IT")

##追加写( a,ab)

  • 没文件时创建文件

  • 永远在文件的末尾添加内容

    f = open("F:\学习\python-lch\作业\day08\l1.txt","a",encoding="utf-8")
    f.seek(0,0)
    print(f.tell())
    f.write("嘿嘿我是李晨浩sb")
    ####在已有的内容后面进行追加
    

##“+”操作

  • r+ 读写 覆盖内容

    # f = open("test","r+",encoding="utf-8")
    # a = f.read()
    # print(a)
    # f.write("这是读写")
    #####此处就是先读   之后在写之前清空
    
    # f = open("test","r+",encoding="utf-8")
    # f.write("这是读写啊")
    # a = f.read()
    # print(a)
    #####此处就是先清空再写   之后再读
    
  • w+ 清空写读

    # f = open("test","w+",encoding="utf-8")
    # f.write("哈哈哈")
    # f.seek(0,0)   # 移动光标   移动到文件的头部
    # print(f.read())
    #####先写   再读
    
  • a+ 追加写读(文件不存在时,实时显示)

    f = open("F:\学习\python-lch\作业\day08\l1.txt","a+",encoding="utf-8")
    f.write("asdasd嘿sss嘿")
    # f.seek(0,0)   # 移动光标   移动到文件的头部
    print(f.read())
    #####直接在已有的内容后面追加
    

##光标seek()

  • seek(0,0) 移动到文件头部
  • seek(0,1) 移动到光标当前位置(没用)
  • seek(0,2) 移动到末尾
  • seek(3) 按照字节移动,根据不同编码决定移动字节大小
  • tell() 查看光标,返回的是字节

##with open

  • 自动关闭文件
  • 可以操作多个文件
  • as 起别名
with open("l1.txt","r",encoding="gbk") as f,\
        open("l2.txt","r",encoding="utf-8")as f1:
    print(f.read())
    print(f1.read())

##os

  • 与操作员系统做交互
export os
os.rename("test","test2") 将test改名为test2

##注意事项:

  • 在不移动光标的情况下,文件中的内容只能读取一次

  • a和w可以创建文件

  • 写的类型必须是字符串

  • w写的时候想加换行符"\n"必须加引号再加上要写的内容

    f.write("\n"+mingdan)
    
  • f.flush() 刷新

  • f.close() 关闭文件

19.迭代器

#迭代器

  • 方法一:

    lst = [1,2,3,4]
    l = lst.__iter__()  #l是迭代器
    print(l.__next__())
    print(l.__next__())
    print(l.__next__())
    print(l.__next__())
    >>>1
       2
       3
       4
    
  • 方法二:(推荐使用)

    lst = [1,2,3,4]
    l = iter(lst)    #l是迭代器
    print(next(l))
    print(next(l))
    print(next(l))
    print(next(l))
    >>>>1
        2
        3
        4
    
  • for循环支持直接循环迭代器

    lst = [1,2,3,4]
    l = iter(lst)
    for i in l:
    	print(i)
    

#for循环本质

  • for循环就是一个迭代器(for循环本质)

    s = "alex"
    s1 = s.__iter__()    #将数据转换成迭代器
    while 1:     #通过死循环不断调用
        try:
            print(s1.__next__())   
        except StopIteration:   #捕获异常,使之不会抛出异常
            break
     >>> a
         l
         e
    

#可迭代对象和迭代器:

  • 可迭代对象(str list tuple)

    • 迭代器也是一个可迭代对象
    • 具有iter()方法的就是一个可迭代对象
    • 优点:1.使用灵活(每个可迭代对象都有自己的方法)

    ​ 2.能够直接查看元素的个数

    • 缺点:1.占内存
    • 当内存大,数据量比较少时,建议使用可迭代对象
  • 迭代器(文件句柄就是一个迭代器)

    • 可next()和iter()的就是一个迭代器
    • 优点:1.节省内存
    • 缺点:1.只能一个方向执行

    ​ 2.一次性的

    ​ 3.不能灵活操作,不能直接查看元素的个数

    • 内存小,数据量巨大时,建议使用迭代器

#时间、空间

  • 时间换空间:迭代器、生成器

  • 空间换时间:可迭代对象,使用大量的空间节省时间

    
    

20.生成器

  • 生成器本身就是一个迭代器,迭代器不一定是生成器
  • 惰性机制
  • 迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3])。生成器是需要我们自己用python代码构建的工具

#基于函数实现的生成器

  • 函数体中存在yield就是定义一个生成器

    def func()
    	print(1)
    	yelid 5
    print(func())     ##函数体中存在yelid就是生成一个生成器
    ##print打印的是一个生成器对象的内存地址 
    
  • 生成器的使用 (next和yelid一一对应)

    方法一:

    def func():
        yield 1     #记录执行位置
        yield 2
        yield 3
    g = func()      #获取生成器的内存地址
    print(next(g))   #获取值
    print(next(g))   #获取值
    print(next(g))   #获取值
    

    方法二:

    def func():
        yield 1     #记录执行位置
        yield 2
        yield 3
    g = func()      #获取生成器的内存地址
    print(next(g))   #获取值
    print(next(g))   #获取值
    print(next(g))   #获取值
    g1 = func()
    print(next(g1))  #重头取值
    print(next(g1))  #取值
    >>>1
       2
       3
       1
       2
    

    方法三:函数嵌套

    def func():
        def foo():
            print(1)
        yield foo
    g = func().__next__()    ##g就是foo的内存地址
    print(g(),type(g))   ##g() == foo()
    >>>1
       None <class 'function'>
    
    

    方法四:列表

    def func():
        yield [1,2,3,4,5,6]
    print(func().__next__(),type(func().__next__()))
    >>>>[1, 2, 3, 4, 5, 6] <class 'list'>
    

    方法五:字典

    def func():
        yield {"name" : 123}
    print(func().__next__(),type(func().__next__()))
    >>>{'name': 123} <class 'dict'>
    
    

    方法六:返回多个

    def func():
        yield 1,2,3,4,5
    print(next(func()))
    >>>>(1, 2, 3, 4, 5)
    

    方法七:yield from

    def func():
        yield from [1,2,3,4,5]
    g = func()
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    

#生成器和迭代器区别:

  • 迭代器:文件句柄,通过数据转换,Python自带提供
  • 生成器:程序员自己实现

#生成器和函数区别

  • 函数是return value ,生成器是yield value 并且能够标记或者记住yield执行的位置,以便下次执行时从标记点恢复执行,
  • yield是函数转换成生成器,但是生成器又是一个迭代器

#时间、空间

  • 空间还时间

    
    
  • 时间换空间

    def func():
        for i in range(1,50001):
            yield i
    g = func()
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    

#区分迭代器和生成器

  • 看内存地址(推荐)
  • 看send()方法
def func()
	yield 1
g = func()
print(g.send())    ###有send就是生成器

#迭代器和生成器的优缺点

  • 优点:1、节省空间

  • 缺点:1、不能直接使用元素

    ​ 2、不能直接查看元素

    ​ 3、使用不灵活

    ​ 4、稍微消耗时间

    ​ 5、一次性的, 不能逆行

#yield功能

  • yield
    • 能返回多个,以元组的形式存储
    • 能返回各种数据类型(Ptyhon的对象)
    • 能够写多个并且都能执行
    • 能够记录执行位置
    • 后边不写内容 默认返回None
    • 能够暂停生成器的运行
    • yield都是将数据一次性返回

#yield from 和 yield区别

  • yield
    • yield是将数据整个返回
  • yield from
    • 将可迭代对象逐个返回

#表达式(推导式)实现生成器

  • 简化代码,提高逼格,提高可读性
  • 生成一些有规律的数据,生成的数据较大时建议使用生成器推导式
  • 推导式最多建议使用三层

#生成器推导式

  • 普通模式

    g = (i for i in range(3))
    print(next(g)) >>>0
    print(next(g)) >>>1
    print(next(g)) >>>2
    
  • 筛选模式

    g = (i for i in range(3) if i+1 == 2)
    print(next(g))
    >>>1
    

#列表推导式

  • 普通循环

    print([i for i in range(1,6)]) >>>[1,2,3,4,5]
    print([i for i in range(1,6,2)]) >>>[1,3,4]
    print([f"Py{i}期" for i in range(1,4)])
    >>>['Py1期', 'Py2期', 'Py3期']
    
  • 筛选模式

    print([i for i in range(1,10) if i > 5])
    >>>[6, 7, 8, 9]
    print([i+j for i in range(2) for j in range(2)])  # 推导式最多建议使用三层
    >>>[0, 1, 1, 2]
    

#字典推导式

  • 普通模式

    print({i:i+1 for i in range(3)})
    >>>{0: 1, 1: 2, 2: 3}
    
  • 筛选模式

    print({i:i+1 for i in range(3) if i >1})
    >>>{2: 3}
    

#集合推导式

  • 普通模式

    print({i for i in range(3)})
    >>>{0,1,2}
    
  • 筛选模式

    print({i for i in range(3) if i >0}) >>>{1,2}
    print({i for i in range(3) if i >2}) >>>set{}
    

#其他

names = [['Tom', 'Billy', 'Jefferson', ],['Alice', 'Jill', 'Ana', 'Wendy']]
print([em for i in names for em in i if "e" in em]) #查找有e的名字
>>>['Jefferson', 'Alice', 'Wendy']
print([em for i in names for em in i if em.count("e")>=2]) #查找名字中带e超过两个的
>>>['Jefferson']
multiples = [i for i in range(20) if i % 3 == 0]
print(multiples) >>>[0, 3, 6, 9, 12, 15, 18]
multiples = [i for i in range(20) if i % 3 is 0]
print(multiples) >>>[0, 3, 6, 9, 12, 15, 18]

21.闭包

  • 闭包的定义
    • 在嵌套函数中,使用非全局变量(且不适用本层变量)
    • 将嵌套函数返回
  • 作用:保持数据安全性,干净性
def func():
    a = 10   # 自由变量
    def foo():
        print(a)
    return foo
f = func()
print(f.__closure__)  # 验证是否是闭包
print(f.__code__.co_freevars)  # 查看自由变量
print(f.__code__.co_varnames)  # 查看局部变量
>>>
(<cell at 0x0000024C254B9048: list object at 0x0000024C25365248>,)
('lst',)
('price', 'arg')
  • 没有将嵌套的函数返回也是一个闭包,但这个闭包不是一个可使用的闭包

    def func():
        a = 10
        def foo():
            print(a)
    func()
    
  • 闭包的应用场景

    • 装饰器
    • 防止数据被误改动
  • 实例(求几次的执行函数的平均值)

    def buy_car():
        lst = []
        def func(price): # price = 1
            lst.append(price)
            arg = sum(lst) / len(lst)
            print(arg)
        return func
    
    f = buy_car()
    print(f.__closure__)
    print(f.__code__.co_freevars)  # 查看自由变量
    print(f.__code__.co_varnames)  # 查看局部变量
    f(1)
    f(2)
    f(3)
    f(4)
    f(5)
    

22.装饰器

  • 装饰器就是在原有基础的功能上添加新的功能的工具

  • 开放封闭原则

    • 对扩展开放,支持增加新功能
    • 对修改的源代码是封闭的,对调用方式是封闭的
  • time

    import time   ###标准库
    def index():
        time.sleep(2)
        print("我真帅")
    index()
    
    

#标准版装饰器

def wrapper(f):
	def inner(*args,**kwargs):
		#被执行函数之前
		ret = f(*args,**kwargs)
		#被执行函数之后
		return ret
	return inner
@wrapper()   ###func=wrapper(func)
def func()
	print("我是被装饰函数")

#实例

####被装饰函数未传参
def wrapper(f):
    def inner(*args,**kwargs):
        print("我是爹,我先走")
        ret = f()  #
        print("你是儿子,你后走")
        return ret
    return inner
@wrapper
def func():
    return "我是女娲"
print(func())
>>>
我是爹,我先走
你是儿子,你后走
我是女娲
####被装饰函数传参
def wrapper(f):
    def inner(*args,**kwargs):
        print("我是爹,我先走")
        ret = f(*args,**kwargs)
        print("你是儿子,你后走")
        return ret
    return inner
@wrapper
def func(a,b,c):
    print(f"我是女娲{a},{b},{c}")
func("ss","ww","yy")

#语法糖

  • 语法糖必须要放在被装饰的函数正上方

  • 语法糖的本质:被装饰的函数=装饰器函数(被装饰的函数)

    import time
    def run_time(f): #f接收的是被装饰的函数名 #run_time就是一个闭包
        def inner(*args,**kwargs): #被装饰的函数需要的参数
            strat_time = time.time()  #被装饰函数之前
            print("外挂开启")
            ret = f(*args,**kwargs)
            print("外挂结束")
            print(time.time() - strat_time)  #被装饰函数之后
            return ret
        return inner
    @run_time   #语法糖的本质---> index=run_time(index)
    def index(user,pwd,hero):
        print("登录游戏")
        print(f"账号{user}密码{pwd}英雄{hero}")
        print("游戏中")
        return "游戏结束"
    print(index('meet','1234','草丛伦'))
    >>>
    

#有参装饰器

  • 应用场景:flask框架的路由就是有参装饰器
##未带参数的装饰器
def wrapper(f):
	def inner(*args,**kwargs):
		#被执行函数之前
		ret = f(*args,**kwargs)
		#被执行函数之后
		return ret
	return inner
@wrapper()   ###func=wrapper(func)
def func()
	print("我是被装饰函数")
##带参数的装饰器
def wark(arg):
    def wrapper(func):
        def inner(*args,**kwargs):
            ret = func1()
            return ret
        return inner
    return wrapper
@wark(chose) 
def func1():
    print("我是被装饰函数")
##wrapper = wark(chose)
##func1 = wrapper(func1)
##func1()

#多个装饰器装饰一个函数

  • 多个装饰器装饰一个函数时先执行离被装饰的函数最近的装饰器

  • 实例

    def f1(func): # func == index
        def f2(*args,**kwargs):
            print("这是f1的装饰开始")
            func(*args,**kwargs)
            print("这是f1的装饰结束")
        return f2
    def foo1(func): # func == f2
        def foo2(*args,**kwargs):
            print("这是foo1的装饰开始")
            func(*args,**kwargs)
            print("这是foo1的装饰结束")
        return foo2
    @foo1      # index = foo1(index)   # index = foo1(f2)
    @f1        # index = f1(index) # 现在的index其实就是返回的f2
    def index():
        print("is index")
    index()   # foo2()
    
    

def f1(func): # func == index
    def f2(*args,**kwargs):
        print("sss")
        func(*args,**kwargs)
        print("stop")
    return f2
def foo1(func): # func == f2
    def foo2(*args,**kwargs):
        print("good")
        func(*args,**kwargs)
        print("bbb")
    return foo2
def ff(func):
    def ff2():
        print("is ff")
        func()
        print("ff is")
    return ff2
@foo1
@ff
@f1
def f():
    print("is f")
f()
>>>
good
is ff
sss
is f
stop
ff is
bbb

23.递归

  • 定义:

    • 不断地调用自己本身,##只满足这个条件的就是死递归
    • 有明确的结束条件
  • 递归最大深度:官方1000 实测994

  • 阶乘5层

    def jc(n):
        if n == 5:
            return 5
        return jc(n+1) * n
    print(jc(1))
    >>>> 120
    
    
  • 斐波那契数列

    lst = [1,1]
    for i in range(5):
        lst.append(lst[-1] + lst[-2])
    print(lst)
    函数:
    还没做出来
    
    

24.函数:

def 函数名():
	函数体

  • 封装代码,减少重复的代码。
  • 函数被调用后,函数体中开辟的空间会被自动销毁
  • 函数名+括号(),有两个功能:第一个是调用函数,第二个是接受返回值
  • 不管在什么位置,只要看到函数名+()就是调用函数

#return

  • 在函数中遇到return直接结束函数
  • 可以给函数的执行者返回任意数据类型
  • 可以给函数的执行者返回多个数据类型(以元组形式接受)
  • 函数体中不写return,默认返回None。写了return不写值,也是返回None
def func():
    print(1)
func()  >>>1  ##不打印函数,只执行函数,只会执行函数体

def func():
    print(1)   ##函数体中不写return,默认返回None
print(func())   
>>>>1
	None      ##只有在print打印函数时,才会打印出None

#函数传参优先级

  • 函数传参优先级:位置参数>*args(动态位置参数)>默认值参数>**kwargs(动态关键字参数)

#参数

  • 形参 : 写在函数声明的位置的变量叫形参(在定义函数的阶段)

    • 可以单独使用位置参数,也可单独使用默认参数,也可混合使用

    • 位置参数:必须要一一对应

      def yue(app,girl,age,addr):    # 形参
          print(f"打开{app}")
          print(f"找一位{girl},要求年龄:{age},地区:{addr}的人")
      yue("微信","女孩",18,"乌克兰")  # 实参  按照位置传参
      
      
    • 默认参数:可以不传,可以传,传的时候会将默认值覆盖

      def userinfo(name,age,hobby,sex="男"):   #sex就有默认值
          print(f"姓名:{name} 年龄:{age} 性别:{sex} 爱好:{hobby}")
      userinfo("岳新力",23,"开车")
      
      
    • 动态位置参数(*args)

      • 在函数定义阶段,*就是聚合
      • 在函数体中,*就是打散list或tuple,**就是打散dict
      • *args 程序员之间的约定俗称(可以更换,但不建议更换)
      • 能够接受不固定长度的参数
      • 位置参数过多时可以使用动态参数
      • 获取到的是一个元组,没有值就是一个空元组
      • 只接受多余的位置参数
      def lst(a,b,c,*args,d=100,):   #*args 此处的*是聚合
          print(a,c,w,d)	        
          print( *args)              #*args 此处的*是打散
          print(args)
      lst(1,2,3,4,5,6,7)
      >>>>1 3 (4, 5, 6, 7) 100
      >>>>4 5 6 7
      (4 5 6 7)
      
      #######################################################################
      
      def foo(a, b, args, c, sex=None, **kwargs):
            print(a,b,c)
            print(args)    #此处的args前没有*   所有没有将列表打散
            print(kwargs)  #此处的kwargs前没有*   所有没有将字典打散
      
      
      
      
    • 动态关键字参数(**kwargs)

    • 在函数定义阶段,*就是聚合

      • 在函数体中,**kwargs就是打散字典,获取到的是键
    • 程序员之间的约定俗称(可以更好,但是不建议更换)

      • 获取到的是一个字典,没有值时就是一个空字典
      • 只接受多余的关键字参数
      def func(**kwargs):   # 万能传参
          print(kwargs)
      func(c=22,a=1,b=2)
      >>>>{'c': 22, 'a': 1, 'b': 2}
      
      
    • 万能传参(面试必问)

      def func(*args,**kwargs):   # 万能传参
          print(args,kwargs)
      func(12,2,121,12,321,3,a=1,b=2)
      >>>>(12, 2, 121, 12, 321, 3) {'a': 1, 'b': 2}
      ###############################################################################
      def foo(a, b, *args, c, sex=None, **kwargs):
          print(a,b,c)
          print(args)
          print(kwargs)
         	print(*args)
          print(*kwargs)
      foo(*[1, 2, 3, 4],**{'name':'太白','c':12,'sex':'女'})   #*[]打散列表  **{}打散字典
      >>>	
      1 2 12
      (3, 4)
      {'name': '太白'}
      3 4
      name
      
      
  • 实参:在函数调用的时候给函数传递的值(调用函数的阶段)

    • 可以单独使用位置参数,也可单独使用关键字参数,也可混合使用
    • 位置参数:必须要一一对应
    • 关键字参数:指名道姓传参
    • 混合参数:位置参数 > 默认参数
    def yue(chat):    # chat  形参   
    
        print("拿出手机")   
    
        print("打开"+chat)   
    
    yue("陌陌")     # "陌陌"在这里就是实参
    
    

#注释

  • 查看函数的注释

    def add(a:int,b:int):  # 提示(a:int)只是提示用户需要传参的类型,不是字典赋值
        """       ####此处的注释必须都是三个双引号(三个单引号也可以)
        加法
        :param a:
        :param b:
        :return:
        """
        return a + b
    print(add(1,2))    >>>>3
    print(add("1","2"))   >>>>12
    print(add.__doc__) 
    >>>>
        加法
        :param a:
        :param b:
        :return:
    
    

#函数的名称空间

  • 名称空间

    • 内置空间 #存放python自带的一些函数
    • 全局空间 #当前python文件定格编写的代码开辟的空间
    • 局部空间 #函数开辟的空间
  • 程序的加载顺序

    ​ 内置空间 > 全局空间 > 局部空间

  • 程序的取值顺序

    ​ 局部空间 > 全局空间 > 内置空间

#作用域

  • 全局作用域: 包含内置命名空间和全局命名空间. 在整个文件的任何位置都可以使用(遵循 从上到下逐⾏执行).
    • globals() 查看全局作用域:内置+全局
  • 局部作用域: 在函数内部可以使用.
    • locals() 查看当前作用域:建议查看局部作用域
def func():
    a = 40
    b = 20
    print("哈哈")
    print(a, b)
    print(globals())    # 打印全局作用域中的内容
    print(locals())     # 打印当前作用域中的内容
func()
>>>>
哈哈
40 20
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001D4A2DDF848>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/学习/python-lch/python26期视频/day10/代码和笔记/06 函数的名称空间.py', '__cached__': None, 'a': 10, 'func': <function func at 0x000001D4A2E97288>}
{'a': 40, 'b': 20}

#函数名的第一类对象及使用

  • 函数名可以当做值,赋值给一个变量

    def func():
        print(1)
    a = func
    print(func)  >>>> # 打印函数的内存地址
    print(a)   #打印函数的内存地址
    a() #执行func函数
    >>>><function func at 0x0000021BB93B7318>
    >>>><function func at 0x0000021BB93B7318>
    >>>>1
    
    
  • 函数名可以当做另一个函数的参数来使用

    def func():
        print(1)
    def foo(a): # a = func
        print(a) # func这个函数的内存地址
    foo(func)   #此处函数foo的参数是func不是func()
    >>>><function func at 0x0000026EC54673A8>
    
    
    def func():    ###被执行,打印一个1
        print(1)
    def foo(a):  ##a = func(), return None
        print(a)   ##将None打印出来
    foo(func())  #此处函数foo的参数是func不是func()
    >>>>1 None
    
    
  • 函数名可以当做另一个函数的返回值

  • 函数名可以当做元素存储在容器中

    def login():
        print("登录")
    
    def register():
        print("注册")
    msg ="""
    1.注册
    2.登录
    请输入您要选择的序号:
    """
    func_dic = {"1":register,"2":login}
    while True:
        choose = input(msg) # "5"
        if choose in func_dic:
            func_dic[choose]()
        else:
            print("滚")
    
    

#函数的嵌套

  • 交叉嵌套
def func():
	foo()
def foo():
	print(111)
func()

  • 嵌套
def func(a,b):   #a = 4 b = 7
    def foo(b,a):  #b = 4 a = 7
        print(b,a)  #4 7
    return foo(a,b) #先执行函数调用  a = 4 b= 7
    # return None 
a = func(4,7)
print(a)
>>>4 7
>>>None

  • global
    • 只修改全局空间中的变量
    • 在局部空间中可以使用全局中的变量,但是不能修改,如果要是要强制修改需要添加global
    • 当变量在全局中存在时,global就是申明我要修改全局的变量,并且会在全局修改这个变量
    • 当变量在全局中不存在时,global就是申明要在全局中创建一个变量,并且会在全局修改这个变量
  • nolocal
    • 只修改局部空间中的变量,最外层的一个函数
    • 只修改离nonlocal最近的的一层,如果这一层没有就继续往上一层进行查找,只能在局部
    • nonlocal不能创建变量

25.匿名函数

  • 匿名函数的名字叫做lambda

  • 匿名函数的编写格式

    f = lambda a,b:a+b
    print(f(1,2)) >>>3
    ####################
    def num():
        return [lambda x:i * x for i in [1,2]]
    a= num()
    print(a) >>>获取到三个内存地址
    
    
    
    print((lambda a,b:a+b)(1,2))
    #lambda和def是一样的
    #a,b和(a,b)是一样的  代表形参
    #: a+b 和 return a+b 是一样的  代表返回值
    # 形参: 可以接受位置参数,动态位置,默认,动态关键,可以不写
    # :返回值 只能返回一个数据,必须写
    
    f = lambda x,y:(x,y,x+y)
    print(f.__name__) >>><lambda>
    print(f(1,2)) >>>(1,2,3)
    
    
  • 例子

    • 算数

      def square(x) :            # 计算平方数
           return x ** 2 
      map(square, [1,2,3,4,5])   # 计算列表各个元素的平方
      [1, 4, 9, 16, 25]
      >>> map(lambda x: x ** 2, [1, 2, 3, 4, 5])  # 使用 lambda 匿名函数
      [1, 4, 9, 16, 25]
      
      
  • 字典

      func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs
      print(func(3, 4,c=666,name='alex')) >>>{'name': 'alex'}
    
    
  • 索引

    func = lambda x:(x[0],x[3])
    print(func('afafasd')) >>>('a', 'f')
    
    
    • 比较大小

      func = lambda x,y: x if x > y else y
      print(func(3,100))  >>>100
      
      

###匿名函数题##

def num():
    return [lambda x:i*x for i in range(3)]  # [func,func,func]
print([m(3) for m in num()])

def num():
    lst = []
    for i in range(3)
        def func(x):
            return i*x
        lst.append(func)
    return lst
new_list = []
for m in num():
    new_list.append(m(3))
print(new_list)

26.软件开发规范

  • 各个文件夹
    • bin ----启动文件
    • lib ----公共组件
    • core ----主逻辑
    • db ----存储数据
    • log ---记录日志
    • conf ---配置文件

27.log日志

  • 记录程序的运行状态
  • 记录用户的操作

#日志的级别

  • debug调试 --10
  • info 信息 --20
  • warning警告 --30
  • error 错误 --40
  • srirical 危险 --50

#日志文件写入

import logging
logger = logging.getLogger()   
#创建一个空架子
fh = logging.FileHandler("test.log",mode = "a",encoding = "utf-8") 
#创建一个文件句柄,用来记录日志
ch = logging.StreamHandler()   
#创建一个屏幕流,打印记录的内容
f_str = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(filename)s %(lineno)s %(message)s")
##d定义一个记录日志的格式
logger.level = 10   #设置一个记录级别
fh.setFormatter(f_str)  #给文件句柄设置记录的格式
ch.setFormatter(f_str)  #给中控台设置打印内容的格式
logger.addHandler(fh)   #将文件句柄添加logger对象中
logger.addHandler(ch)   #将中控台添加的logger对象中
logger.debug(1234)
logger.info(1234)
logger.warning(1234)
logger.error(1234)
logger.critical(1234)

28.包

  • 具有—init—.py文件的文件夹就是一个包,目的就是管理模块
  • 包的本质就是一个模块,模块可以导入,包也可以导入
Python2中,使用import一个包时,包中没有--init--.py报错
Python3中,使用import一个包时,包中没有--init--.py不报错

  • 导入时,发现使用.(点)的操作就是导入包
  • 导入前.(点)前面必须是一包

#路径

  • 绝对路径:从最没外层的开始查找
  • 相对路径:取决于在哪个文件中启动

#import 包.包.模块

  • import bake.api.versions
    ##bake是包  api也是包   version是模块
    
    

#起别名

  • import bake1.api.versions as v
    
    

#from 包.包.模块 import 函数,变量,*

29垃圾回收机制

  • 概述:python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略
  • 引用计数:
    • 每当新的引用指向该对象时,引用计数加1,当对该对象的引用失效时,引用计数减1,当对象的引用计数为0时,对象被回收。缺点是,需要额外的空间来维护引用计数,并且无法解决对象的循环引用。
  • 分代回收:
    • 以时间换空间的回收方式
    • 分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。
    • 新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。
    • 同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象
  • 标记清除:
    • 活动对象会被打上标记,会把那些没有被打上标记的非活动对象进行回收。

30什么是断言

  • assert是用来检查一个条件,如果它为真,就不做任何事。如果它为假,则会抛出AssertError并且包含错误信息。
  • 应用场景:
    1. 防御型编程
    2. 运行时检查程序逻辑
    3. 检查约定
    4. 程序常量
    5. 检查文档
posted @ 2019-01-09 23:01  Na_years  阅读(117)  评论(0编辑  收藏  举报