Python基础2

Posted qmuy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python基础2相关的知识,希望对你有一定的参考价值。

Python基础2

函数 - 面向过程编程

初识函数

  • 函数 :函数是以功能为导向,一个函数封装一个功能,登录,注册,评论,文件操作等

  • 优点:减少代码重复,提高代码的可描述性

  • #获取任意一个字符串的元素的个数
    s1 = 'fdskjlgfdgfdjkslgdfjkjafdsajk'
    count = 0
    for i in s1:
        count += 1
    print(count)
    
    
    #获取列表的元素的个数
    l1 = [1, 2, 3]
    count = 0
    for i in l1:
        count += 1
    print(count)
    
    # 利用函数
    l1 = [1, 2, 3]
    def new_len():
        count = 0
        for i in l1:
            count += 1
          print(count)
    new_len()

函数的结构

  • def func() :

    ?? ??

    关键字 函数名 () 和:结构需要

    • 函数名 : 与变量名命名规范一致,一定具有可描述性

    • l1 = [1, 2, 3]
      def new_len():
          count = 0
          for i in l1:
              count += 1
              print(count)
      new_len()

函数的调用 ***

函数名() → 函数的执行者/函数的调用者, 出现几次,这个函数就执行几次

l1 = [1, 2, 3]
def new_len():
    count = 0
    for i in l1:
        count += 1
    print(count)

函数的执行写多少次,执行多少次。
new_len() # 函数名() 函数的执行者。调用者。
new_len()  # 函数名() 函数的执行者。
new_len()  # 函数名() 函数的执行者。
new_len()  # 函数名() 函数的执行者。
new_len()  # 函数名() 函数的执行者。

l1 = [1, 2, 3]
def new_len():
    count = 0
    for i in l1:
        count += 1
    print(count)

for i in range(10):
    print(111)
    
for i in range(3):
    new_len()

函数的返回值

  • 函数的返回值 - 返回给函数的执行者

  • #一个函数就是封装一个功能,这个功能一般都会有一个最终结果的,比如你写一个登录函数,最终登录成功与否是不是需要返回你一个结果?还有咱们是不是都用过len这个函数,他是获取一个对象的元素的总个数,最终肯定会返回一个元素个数这样的结果:
    s1 = 'abfdas'
    print(len(s1))  # 6
  • 函数中的return作用 :

  • 1.结束函数,后面的代码统统不执行,只能在函数中用
    2.给函数的执行者返回具体的值
  • l1 = [1, 2, 3]
    def new_len():
        print(111)
        print(222)
        if 1 == 1:
            return
        print(333)
        print(444)
    new_len()
    #结果
    111
    222 
  • 函数中如果没有return,或者程序中只有一个return,函数的执行者得到的是None

  • l1 = [1, 2, 3]
    def new_len():
        count = 0
        for i in l1:
            count += 1
        return
    print(new_len())
    # 结果 :    None
  • 函数中return后面是单个值,则返回这个值(值类型不改变)

  • def func():
        print(111)
        # return 100
        # return [1, 2, 3]
        return 'name': '哈哈'
    ret = func()
    print(ret, type(ret))
    # 结果 :
    111
    'name': '哈哈' <class 'dict'>
  • 函数中return后面是多个值,函数的执行者得到的是一个人元组

  • def func():
        print(111)
        return 1, '走你', [22, 33]
    ret = func()
    print(ret, type(ret))  # (1, '走你', [22, 33])
    
    
    def func():
        print(111)
        # return 1+1+2
        return 2 > 1 # 返回结果
    ret = func()
    print(ret)
    # 结果
    111
    True

函数的传参

  • 之前的函数都是写死的,现在引出函数的传参,使代码更简便

  • 函数的传参 - - 函数的拓展性

  • def new_len(a):  # 定义函数时:参数:形参。
        count = 0
        for i in a:
            count += 1
        return count
    l1 = [1, 2, 3]
    print(new_len(l1)) # 函数的调用者:参数 实参。

    实参角度 :

    1. 位置参数
    # 1. 位置参数。: 从左至右,按照顺序,一一对应
    def meet(sex,age,job,):
        print('左划一下')
        print('右划一下')
        print(f'寻找性别sex,年龄age岁,job')
    
    meet('女','18~25','讲师')
    
    #写一个函数,接收两个数字的参数,将较大的数字返回。
    def comp(a,b):
        if a > b:
            return a
        else:
            return b
    ret = comp(1,2000)
    print(ret)

    三元运算符:简单的if else。

    a1 = 1
    b2 = 2
    ret = a1 if a1 > b2 else b2
    print(ret)
    
    def comp(a,b):
        # ret = a if a > b else b
        # return ret
        return a if a > b else b
    ret = comp(1,2000)
    print(ret)
    2. 关键字参数

    ? 参数要一一对应

    def meet(sex,age,job,hight,weight,):
        print('左划一下')
        print('右划一下')
        print(f'寻找性别sex,年龄age岁,身高hight,体重weight,工作job')
    
    meet(sex='女',job='学生',weight=120,hight=170,age='18~25')
    3.混合参数

    ? 关键字参数一定要在位置参数后面,遵循一一对应

    def meet(sex,age,job,hight,weight,):
        print('左划一下')
        print('右划一下')
        print(f'寻找性别sex,年龄age岁,身高hight,体重weight,工作job')
    
    meet('男',22,'ITC语言',weight=120,hight=175,)

    形参角度 :

    • 1.位置参数 : 与实参角度位置参数一样

    • def meet(sex,age,job):
          print('左划一下')
          print('右划一下')
          print(f'寻找性别sex,年龄age岁,job')
      
      meet('女','18~25','幼师')
    • 2.默认参数 : 一定要写在位置参数后面 , 不传参即沿用默认参数

    • # open('文件的改',encoding='utf-8')
      def meet(age,job,sex='女'):
          print('左划一下')
          print('右划一下')
          print(f'寻找性别sex,年龄age岁,job')
      
      # meet('18~25','幼师')
      # 更改默认参数
      # meet('18~25','幼师',sex='laddy_boy')
      meet('18~25','幼师','laddy_boy')

    万能参数

    ? 形参角度 : 第三种传参方式 → 万能参数py

    def eat(food1,food2,food3):
        print(f'我请你吃:food1,food2,food3')
    eat('蒸羊羔','蒸熊掌','蒸鹿尾')
    #当给函数传入的参数数目不定时,之前的传参方式解决不了问题。
    
    万能参数 - 动态参数 :
    • *args
    def eat(*args):  # 将实参角度:定义一个函数时,* 所有的位置参数聚合到一个元组中。
        print(args)
        print(f'我请你吃:args')
    eat('蒸羊羔','蒸熊掌','蒸鹿尾','烧花鸭','烧企鹅')
    # 结果
    ('蒸羊羔', '蒸熊掌', '蒸鹿尾', '烧花鸭', '烧企鹅')
    我请你吃:('蒸羊羔', '蒸熊掌', '蒸鹿尾', '烧花鸭', '烧企鹅')
    
    # 函数接收不定个数的数字实参,将最终的和返回出去。
    def sum1(*args):
        # print(args)  (100, 2, 67, 3)
        result = 0
        for i in args:
            result += i
        return result
    print(sum1(100,2,67,3))
    # 结果 :172
    
    • ** kwargs
    def func(**kwargs):  # 函数的定义时:**将实参角度所有的关键字参数聚合成了一个字典,给了kwargs.
        print(kwargs)
    func(name='alex',age=84,hobby='唱跳rap篮球')
    # 结果 :'name': 'alex', 'age': 84, 'hobby': '唱跳rap篮球'
    
    • 万能参数
    # *args,**kwargs 万能参数
    def func(*args,**kwargs):
        print(args,kwargs)
    func(1,2,4,'fjdksal',age=84,hobby='唱跳rap篮球')
    # 结果 :(1, 2, 4, 'fjdksal') 'age': 84, 'hobby': '唱跳rap篮球'
    
    • *的魔性用法(函数中)
    def func(*args,**kwargs):
        print(args)  
        print(kwargs)
    l1 = [1, 2, 3]
    l2 = ['太阳', 'moon', '云朵']
    func(l1,l2)
    # 结果:
    ([1, 2, 3], ['太阳', 'moon', '云朵'])
    
    
    func(*l1,*l2)  # 当函数的执行时:*iterable 代表打散。
    # 结果 :
    (1, 2, 3, '太阳', 'moon', '云朵')
    
    
    func(*[1, 2, 3],*(11,22),*'fdsakl')  # 当函数的执行时:*iterable 代表打散。
    # 结果:
    (1, 2, 3, 11, 22, 'f', 'd', 's', 'a', 'k', 'l')
    
    
    # 当函数的执行时:**dict 代表打散。
    def func(*args,**kwargs):
        print(args)
        print(kwargs)
    func(**'name':"alex",**'age': 73,'hobby': '吹')
    # 结果 :
    ()
    'name': 'alex', 'age': 73, 'hobby': '吹'
    
    • 函数外: 处理剩余元素

    • a,b,*c = [1,2,3,4,5]
      print(a,b,c) #  1 2 [3, 4, 5]
      
      a,*c,b, = [1,2,3,4,5]
      print(a,b,c) # 1 5 [2, 3, 4]
      
      a,*c = range(5)
      print(a,c) #  0 [1, 2, 3, 4]
      
      a,*c,b = (1,2,3,4,5,6)
      print(a,c,b) # 1 [2, 3, 4, 5] 6
      
    • *args的位置

      • *args不能放在位置参数前面,a,b取不到值

        def func(*args,a,b,sex='man',):
            print(a)
            print(b)
            print(sex)
            print(args)
            # print(kwargs)
        func(1,2,4,5,6) # 报错
        
      • *args如果想要接收到值之前,肯定要改变sex默认参数。

        def func(a,b,sex='man',*args):
            print(a)
            print(b)
            print(sex)
            print(args)
        func(1,2,4,5,6)
        # 结果:
        1
        2
        4
        (5, 6)
        
        
        def func(a,b,*args,sex='man'):
            print(a)
            print(b)
            print(sex)
            print(args)
        func(1,2,4,5,6)
        # 结果 :
        1
        2
        man
        (4, 5, 6)
        func(1,2,4,5,6,sex='women')
        # 结果 :
        1
        2
        women
        (4, 5, 6)
        
        **kwargs

        含参函数的形参位置 :

        位置参数 → *args → 默认参数 → 仅限关键字参数 → **kwargs

        def func(a,b,*args,sex='man',**kwargs,):
            print(a)
            print(b)
            print(sex)
            print(args)
            print(kwargs)
        func(1,2,4,5,6,name='星星',age=18)
        # 结果 :
        1
        2
        man
        (4, 5, 6)
        'name': '星星', 'age': 18
        

        形参角度第四种传参方式:仅限关键字参数

        # 位置参数,*args,默认参数,仅限关键字参数,**kwargs
        def func(a,b,*args,sex='man',c,**kwargs,):
            print(a)
            print(b)
            print(sex)
            print(c)
            print(args)
            print(kwargs)
        func(1,2,4,5,6,67,c=666,name='阿坤',age=18,)
        # 结果:
        1
        2
        man
        666
        (4, 5, 6, 67)
        'name': '阿坤', 'age': 18
        
        简单了解时间模块
        import time #导入时间模块
        print(time.time()) # time.time 为时间戳
        print(111)
        time.sleep(1) # 让程序静止1秒
        age = 18
        print(age)从空间角度研究函数
        

从空间角度研究函数

#变量 (函数名也叫变量)

input = 666
print(input)
# 从全局寻找input ————> 全局名称空间 ——————> 内置

input = '太白'
def func():
    #input = 666
    print(input)
func()
#从局部寻找input ——————> 局部名称空间 ————> 全局名称空间 ——————> 内置
# 取值顺序:单向不可逆

def func():
    name = 'moon'
func()
print(name) #全局找name --> 内置(不会在局部找)


name = '阿坤'
def func():
    #name = 'moon'
    def inner():
        print(name) # 先在局部找,如果局部没有,去全局找,然后内置
    inner()
func()

内置函数的研究 globals locals

name = 'moon'
l1 = [1, 2, 3]

def func():
    age = '18'
func()
print(globals()) # 全局作用域所有的内容
print(locals())  # 当前位置

三个小练习

# 例1:

# def func1():
#     print('in func1')
#     print(3)
# def func2():
#     print('in func2')
#     print(4)
#
# func1()
# print(1)
# func2()
# print(2)
'''
in func1
3
1
in func2'
4
2
---------------------------------------------
# 例2:
def func1():
    print('in func1')
    print(3)
def func2():
    print('in func2')
    func1()
    print(4)
print(1)
func2()
print(2)

'''
1
in func2
in func1
3
4
2
-----------------------------------------------
# # 例3:
#
def fun2():
    print(2)
    def func3():
        print(6)
    print(4)
    func3()
    print(8)

print(3)
fun2()
print(5)
#//3 2 4 6 8 5

关键字

count = 0
def func():
    count += 1
func()
# UnboundLocalError: local variable 'count' referenced before assignment
# 解释器认为:如果你在局部作用域对一个变量进行修改了,解释器认为你在局部作用域已经定义好这个变量了。但现在你并没有定义这个变量,所有报错了

1. 在局部作用域声明一个全局变量 : global - (剪切)

def func():
    global name
    name = 1
    print(globals())
    # print(locals())
    name += 1
    print(globals())
func()
# print(name)
print(globals())

2. global - 可以修改全局变量

count = 0
def func():
    global count
    count += 1
print(count)
func()
print(count)

3. 在局部作用域声明一个局部变量 - nonlocal - (复制)** - - → 不能操作全局变量

# nonlocal可以对父级作用域的变量进行修改,并且在当前作用域创建(复制)一份此变量。
def func():
    count = 0
    def inner():
        nonlocal count
        count += 1
        print(count)
        print(locals())
    inner()
    print(locals())
func()
#UnboundLocalError: local variable 'count' referenced before assignment
#解释器认为:如果你在局部作用域对一个变量进行修改了,
#你在局部作用域已经定义好这个变量了。

4. 默认参数的坑

def func(a,b=False):
    print(a)
    print(b)
func(1,True)
#当你的默认参数如果是可变的数据类型,你要小心了。
#?
def func(a,l=[]):
    l.append(a)
    return l
print(func(1))  # [1,]
print(func(2))  # [1,2]
print(func(3))  # [1,2,3]

函数名的应用

1. 函数名指向的是函数的内存地址,加上()就执行这个函数 : → func()

函数名是一个特殊的变量。
def func():
    print(666)
print(func)  # func = <function func at 0x00000000003F1EA0>

2. 函数名是一个变量。

def func():
    print(666)
f1 = func
f2 = f1
f2()
f1()

3. 函数名可以作为容器类类型的元素。

def func1():
    print('in func1')
def func2():
    print('in func2')
def func3():
    print('in func3')
l = [func1, func2, func3]
print(l)
for i in l:
    i()
# 结果:
[<function func1 at 0x10849fea0>, <function func2 at 0x10875f488>, <function func3 at 0x10875f268>]
in func1
in func2
in func3

4. 函数名可以作为函数的实参。

a = 1
def func(argv):
    print(argv)
func(a)


def func1():
    print('in func1')
def func2(argv):
    argv()
    print('in func2')
func2(func1)

5. 函数名可以作为函数的返回值。

b = 666
def func1():
    print('in func1')
def func2(argv):
    print('in func2')
    return argv
ret = func2(b)
print(ret)


def func1():
    print('in func1')
def func2(argv):
    # argv = func1 : function 43543
    print('in func2')
    return argv
ret = func2(func1)  # func1 : function 43543
ret()



def wrapper():
    def inner():
        print(666)
    return inner
# ret = wrapper()
# ret()
wrapper()()

格式化输出f

#f不区分大小写
num = input('>>>')
s = F'pythonnum'
print(s)


#可以加入表达式
s1 = 'moon'
s2 = f'我的名字s1.upper()'
print(s2)


l1 = ['阿坤', 18, 176]
s1 = f'我的名字l1[0],我的年龄l1[1],我的身高l1[2]'
print(s1)


#可以结合函数
def func(a,b):
    return a + b
s1 = f'最终的结果func(1,3)'
print(s1)


#不能放一些特殊的字符 ! , :   ;
print(f"替换结果73")
print(f'12,')

可迭代对象

# 字面意思分析 : 可以重复的迭代的实实在在的东西
# list,dict(keys(),values(),items()),tuple,str,set,range, 文件句柄
# 专业角度:内部含有'__iter__'方法的对象,就是可迭代对象.
# 内置函数 :dir()   print(dir(str))
# 判断一个对象是不是可迭代对象 : print('__iter__' in dir(str))
# 优点:
            1.直观    2.操作方法较多
# 缺点:
            1.占内存   2.不能迭代取值(索引,字典的key)

1. 判断迭代对象

# str  list
# 内置函数:dir()→ 用来查方法
print(dir(str)) # 返回的表中有'__iter__' 就是可迭代对象

print('__iter__' in dir(str)) # True

2. 迭代器

# 字面意思 :可以重复迭代的工具
# 专业角度 : 内部含有'__iter__'并且'__next__'方法的对象,就是迭代器
# 优点 :
            1. 非常节省内存.  2.惰性机制
# 缺点 :
            1.不直观   2.操作不灵活 3.效率相对低
# 特性
l1 = [22, 33, 44, 55, 66, 77]
obj = iter(l1)
for i in range(3):
    print(next(obj))
for i in range(2):
    print(next(obj))

 
# 可迭代对象与迭代器的对比:
#       可迭代对象:可迭代对象是一个操作比较灵活,直观,效率相对高,但是比较占用内存的数据集。
#       迭代器:迭代器是一个非常节省内存,满足惰性机制,但是效率相对低,操作不灵活的数据集。

利用while循环,模拟for循环内部循环可迭代对象的机制。

#    先要将可迭代对象转化成迭代器。
#    利用next对迭代器进行取值。
#    利用异常处理try一下防止报错。
s = 'gkffdsa;lfkdsk;lafkds;laldgjfd'
obj = iter(s)
while 1:
     try:
         print(next(obj))
     except StopIteration:
         break
with open('调试',encoding='utf-8',mode='w') as f1:
    print(f1)
print(zip('fdsa','fdsagdfsg'))  # <zip object at 0x00000000029B1D88>
# 将zip函数中的两个可迭代对象参数按对应索引值进行匹配组合,得到zip对象。(拉链式函数)

3. 可迭代对象转化成迭代器 iter()

l1 = [1, 2, 3, 4, 5]
# 内置函数iter()
obj = iter(l1)  # l1.__iter__()
print(obj)  # <list_iterator object at 0x0000000001DEA2E8>

4. 迭代器可以迭代取值。利用next()进行取值

l1 = [1, 2, 3, 4, 5]
# 内置函数iter()
obj = iter(l1)
print(obj)  #<list_iterator object at 0x1055828d0>
print(next(obj)) # 1
print(next(obj)) # 2
print(next(obj)) # 3
print(next(obj)) # 4
...
#迭代器一条路走到底,不走回头(记录位置)。
# next超过元素会报错
for i in range(3):
    print(next(obj))
    
for i in range(2):
    print(next(obj))

生成器

1. 生成器函数 yield

def func():
    print(111)
    return 2
ret = func()
print(ret)
# 结果 :
111
2
# 执行此函数,遇到return结束函数。
# 将数字2返回给ret。
def func():
  print(111)
  yield 222
  yield 333
func()
# 结果 : 无


def func():
  print(111)
  yield 222
  yield 333
  yield 2,3,4
ret = func()
print(next(ret)
print(next(ret)   
print(next(ret)
print(next(ret)   
# 结果:
111
222
333
(2,3,4)
5.0
++++++++++++++++++++++++++++++++     
++++++++++++++++++++++++++++++++
# 01
a = 5
def func():
    global a
    a = 1
    yield 1
func()
print(a)
# 结果 :5
============================
# 02
a = 5
def func():
    global a
    a = 1
    yield 1
func()
print(next(func()))
print(a)
# 结果 :
1
1
============================
# 03
def func():
    yield 1
    print('哈哈')
func()
# 结果 :空

# 总结 : 在带有yield的函数中,若没有执行next(),则yield前后都不会执行

与迭代器一样,当程序运行完最后一个yield,再次运行next(),程序会报错

说明一个yield对应一个next,next超过yield数量,就会报错

# 只要函数中出现了yield那么他就不是函数,它是生成器函数。
# 一个next对应一个yield.
print(next(ret))
print(next(ret))
print(next(ret))
print(next(ret))

# return yield
# return 结束函数,给函数的执行者返回值(多个值通过元组的形式返回)。
# yield  不结束函数,对应着给next返回值(多个值通过元组的形式返回)。

yield与return的区别:

  • return一般在函数中设置一个,,他的作用是终止函数,并且给函数的执行者返回值
  • yield在生成器函数中可设置多个,且并不会终止函数,next会获取对应yield生成的元素
# 举例说明:
def eat_baozi():
    list1 = []
    for i in range(1,2001):
        list1.append(f'i号包子')
    return list1
print(eat_baozi())

def eat_baozi_gen():
    for i in range(1,2001):
        # print(11)
        yield f'i号包子'
ret = eat_baozi_gen()  #这是一个生成器
print(ret)
# 结果 :<generator object eat_baozi_gen at 0x0000020584B84CA8>
print(next(ret))  # 生成器,可以用next()函数一个一个打印出来
print(next(ret))
# 结果
1号包子
2号包子


#下一次打印的包子序号会接着上一次打印,也就是说,生成器会停留在最后一次打印(取出)元素的位置上
ret = eat_baozi_gen()
for i in range(200):
    print(next(ret))
for i in range(200):
    print(next(ret))
def func():
    l1 = [1, 2, 3]
    yield l1
ret = func()
print(next(ret))
print(next(ret))
print(next(ret))
因为函数中yield只有一个,而next()有多个,所有会报错

yield from :

可以直接把迭代对象中的每一个数据作为生成器的结果进行返回

def func():
    l1 = ['one', 'two', 'three']
    yield from l1
    yield 1
    yield 2
    yield 3
ret = func()
print(next(ret))
print(next(ret))
print(next(ret))
print(next(ret))
print(next(ret))
"""
结果:
one
two
three
1
2
"""
# yield : 对应next给next返回值
# yield from 将一个可迭代对象的每一个元素返回给next
# yield from 节省代码,提升效率(代替了for循环)

2. 推导式

1. 列表推导式

l1 = [1,2,3......100]
l1 = []
for i in range(1,101):
    l1.append(i)
print(l1)

# 列表推导式
l1 = [i for i in range(1, 101)]
print(l1)

列表推导式的两种构建方式

# 1.循环模式: [变量(加工后的变量) for 变量 in iterable]
# 2.筛选模式: [变量(加工后的变量) for 变量 in iterable if 条件]
    1. 循环模式 :

      # 将10以内所有整数的平方写入列表。
      print([i**2 for i in range(1, 11)])
      
      # 100以内所有的偶数写入列表.
      print([i for i in range(2, 101, 2)])
      
      # 从python1期到python100期写入列表list
      print([f'pythoni期' for i in range(1, 101)])
      
    1. 筛选模式 :

      #一百以内大于49的数的列表
      print([i for i in range(1, 101) if i > 49])
      
      # 三十以内可以被三整除的数。(列表)
      print([i for i in range(1, 31) if i % 3 == 0])
      
      # 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
      l1 = ['barry', 'fdsaf', 'alex', 'sb', 'ab']
      print([i.upper() for i in l1 if len(i) > 3])
      
      # 找到嵌套列表中名字含有两个‘e’的所有名字(有难度)
      names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
               ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
      l1 = []
      for i in names:
          for j in i:
              if j.count('e') > 1:
                  l1.append(j)
      print(l1)
      
      print([j for i in names for j in i if j.count('e') > 1])
      
  • 列表推导式的优缺点:
# 优点:
    # 1, 简单,快捷,装b。
# 缺点:
    # 2. 可读性不高,不好排错。

# 慎用,不要入迷。

2. 生成器表达式

# 生成器表达式:
# 与列表推导式几乎一模一样。
# 循环模式,筛选模式。

obj = (i for i in range(1, 11))
print(obj)
print(next(obj))
print(next(obj))
print(next(obj))
# # 如何触发生成器(迭代器)取值?
# # 1. next(obj)
# # 2. for 循环
# # for i in obj:
# #     print(i)
# # 3. 数据转化
# print(list(obj))

# 生成器表达式:生成器 节省内存。
# 字典推导式,集合推导式:  两种模式: 循环模式,筛选模式

l1 = ['小潘', '怼怼哥','西门大官人', '小泽ml亚']
# 0: '小潘', 1: '怼怼哥', 2: '西门大官人'
dic = 
for index in range(len(l1)):
    dic[index] = l1[index]
 print(dic)
# 0: '小潘', 1: '怼怼哥', 2: '西门大官人'

print(i:l1[i] for i in range(len(l1)))
# 0: '小潘', 1: '怼怼哥', 2: '西门大官人'


# 1~100
print(i for i in range(1, 101))

匿名函数

匿名函数只能构建简单的函数,一句话函数 一般与lambda配合使用

def func(x,y):
    return x + y
# print(func(1, 2))

# 匿名函数构建
func2 = lambda x,y: x + y
print(func2(1, 2))

# 匿名函数最常用的就是与内置函数结合使用。

# 写匿名函数:接收一个可切片的数据,返回索引为 0与2的对应的元素(元组形式)。
func = lambda x: (x[0],x[2])
print(func('太白金星'))

# 写匿名函数:接收两个int参数,将较大的数据返回。
func1 = lambda x, y: x if x > y else y
print(func1(100,2))

func2 = lambda : 3
print(func2()) # 3
函数:
# str() dir() range() len() print() max() min() open()
# input() type() int() enumerate() list() id() set() dict()
# iter() next() tuple() bool() globals() locals() frozenset()

内置函数

# eval exce     慎用

eval:
s1 = "1: 'alex'"  →  eval(s1) 输出结果 :1: 'alex'
s2 = '1 + 3'    →eval(s2) 输出结果 :4 
eval 剥去字符串的外衣,返回里面的本质
# 前提条件 是字符串(str)
    若字符串里面的是数字,且里面有运算,则会直接输出结果
    
    
# exec 执行字符串类型的代码,(执行str里面的可执行代码)

s3 = '''
    for i in range(3):
         print(i)
     '''
exec(s3)
# 结果 : 执行s3里面的for循环,打印:0 1 2
# hash() 获取一个可哈希对象(int ,str ,bool,tuple..)的值
print(hash(123214134))
print(hash('fkljdsaklgjdfs'))
print(hash('gjdfs'))
# help() 查看函数或模块用途的详细说明
print(help(str.count))
# callable  ** 用于查看一个人对象是否可调用,若返回True,程序可能会报错,但是返回False.肯定会失败
name = 'alex'
def func():
    pass
print(callable(name))  # False
print(callable(func))  # True
# int  ** 用于将一个字符串或数字转化为整型
print(int(3.14))
print(int('123'))
print(float(100)) # 将整数和字符串转换成浮点数
print(complex(1,2)) #函数用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。。
print(bin(100))  # 将十进制转化成二进制。 **
print(oct(10)) # 将十进制转化成八进制字符串并返回。
print(hex(17)) # 将十进制转化成十六进制字符串并返回。 **

# 将其他进制转换成10进制:
print(int('1010',2))
print(int('12',8))
print(int('a',16))

print(divmod(10, 3)) # 结果:(5, 0)  **
# 计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)分页用到
print(round(3.1485926,2)) #结果 :print(round(3.1485926,2))
# 保留小数的有效位置 默认保留整数,保留遵循四舍五入原则
print(pow(3, 3))  # 求x的y次幂.(三个参数为x**y的结果对z取余)
print(pow(3, 3, 2))
print(ord('a')) # 输入字符寻找其在unicode的位置。
print(ord('中'))
print(chr(98))  # **  # 输入位置数字找出其对应的字符
print(chr(20104))  # 予
print(repr('太白'))  #  结果 :'太白'   repr 原形毕露  **
l1 = [1, 'fgdsa', [], 1: 2]
l2 = [0, '', [], ]
print(all(l1)) # 判断可迭代对象元素全部都为True,返回True
print(any(l2))  # 判断可迭代对象元素只要有一个True返回True
sep # 设定分割符。
end # 默认是换行可以打印到一行
print(1, 2, 3, sep='|')
print(1, 2, end=' ')
print(3, 4)
f = open('log','w',encoding='utf-8')
 # f.write('写入文件')
print('写入文件', file=f)
list
# l1 = list('fdsafd')
# print(l1)
dict
# 创建字典的几种方式
dic = 1: 2
dic = dict(one=1, two=2, three=3)
dic = dict.fromkeys(可迭代对象,每一个key的值)
print(i: 1 for i in range(3))
# 字典推导式
print(i: 1 for i in range(3))
# abs()  获取绝对值
print(abs(-10))
# sum() 数字相加求和
# sum(iterable,)
print(sum([1,2,3,4]))
print(sum([1, 2, 3, 4], 100)) # 结果 : 110


#####  非常非常非常重要的  #####

# min 可以加功能
print(min([22, 11, 45, 2]))  # 结果 : 2

#找年龄最小的元组
l1 = [(73, 'alex'), (35, '武大'), (18, '太白')]
print(min(l1)) #返回的是这个组成列表的元组  (18, '太白')

l1 = [('alex', 73, 170), ('太白', 18, 185), ('武大', 35, 159),]
# # 通过设置key去使用min
# # key = 函数名
# # def func(x):  # x = ('alex', 73)
# #     return x[1]

# # 返回值是什么就按照什么比较最小的。

# # min 会自动的将可迭代对象的每一个元素作为实参传给x,
'''
第一次,x = ('alex', 73)   73
第二次,x = ('武大', 35)   35
第三次,x = ('太白', 18)   18
'''

# 将遍历的那个元素即是 ('太白', 18) 返回
# print(min(l1,key=func))
# print(min(l1,key=lambda x: x[1]))


# def func(x):
#     return x[1]
# print(min(l1,key=func))
# print(min(l1,key=lambda x: x[1]))
# print(min(l1,key=lambda x: x[2])[0])
# 练习:
dic = 'a':3,'b':2,'c':1
# 将dic值最小的键返回。
print(min(dic,key= lambda x:dic[x]))
# 将dic值最小的值返回。
# print(dic[min(dic,key= lambda x:dic[x])])
dic = 'A':['李业', 67],'b': ['怼哥', 95],'c': ['冯垚', 85]
# 将成绩最低的从属于的那个列表返回。
print(dic[min(dic,key=lambda x:dic[x][1])])
# 将成绩最低的分数返回。
print(dic[min(dic,key=lambda x:dic[x][1])][1])


# max() 与min 用法相同。


# reversed()  对一个可迭代对象进行翻转,返回一个迭代器
s1 = 'alex'
print(reversed(s1)) #// <reversed object at 0x0000023442C3B278>
for i in reversed(s1):
    print(i)
# 结果 :
x
e
l
a

# 内置函数:bytes()
s1 = '太白'
# 方法一:
print(s1.encode('utf-8')) #  b'\xe5\xa4\xaa\xe7\x99\xbd'
# 方法二:
print(bytes(s1,encoding='utf-8')) #  b'\xe5\xa4\xaa\xe7\x99\xbd'


# 解码:
b1 = b'\xe5\xa4\xaa\xe7\x99\xbd'
# 方法一:
print(b1.decode('utf-8'))
# 方法二:
 print(str(b1, encoding='utf-8'))
# 继续min()

dic = 'c': 1, 'b': 2, 'a': 3
# 最小的值对应的键返回
print(min(dic))
print(min(dic,key=lambda x:dic[x]))
# min 会自动将dic的每个key依次传给x,返回值设定什么,就按照什么比较大小。
# 最后将x返回。
# 最小的值对应的值返回
print(dic[min(dic, key=lambda x:dic[x])])

list = [
    'name': 'alex', 'age': 73,
    'name': 'wusir', 'age': 35,
    'name': '太白', 'age': 25,
 ]
# 将年龄最小的 字典返回。
print(min(list,key=lambda x: x['age']))
# 将年龄最小的名字返回。
print(min(list,key=lambda x:x['age'])['name'])
# 将年龄最小的年龄返回。
print(min(list,key=lambda x: x['age'])['age'])

# zip 拉链方法 返回一个迭代器
#函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,
#然后返回由这些元祖组成的内容,如果各个迭代器的元素个数不一致,则按照长度最短的返回,
l1 = [1, 2, 3, 4]
tu = ('a', 'b', 'c')
s = 'python23'
# # print(zip(l1,tu,s))
print(list(zip(l1,tu,s)))
#结果 :[(1, 'a', 'p'), (2, 'b', 'y'), (3, 'c', 't')]

# sorted 排序
l1 = [2, 6, 4, 1, 3]
# 列表原有的方法
l1.sort()
print(l1)
# 形成新列表
print(sorted(l1))
print(l1)

list1 = [
    'name': 'alex', 'age': 73,
    'name': 'wusir', 'age': 35,
    'name': '太白', 'age': 25,
]
# 加key
print(sorted(list1))
print(sorted(list1, key=lambda x:x['age']))
print(sorted(list1, key=lambda x:x['age'],reverse=True))
#
l1 = [('张一东', 80), ('张耳洞', 75), ('怼怼哥', 7), ('李业', 59)]
print(sorted(l1,key=lambda x:x[1]))
print(sorted(l1,key=lambda x:x[1],reverse=True))

# filter  返回一个生成器
# 生成器表达式的筛选模式
l1 = [56, 67, 12, 34, 78, 90,]
print([i for i in l1 if i > 60])
# 返回值为True的留下来
print(filter(lambda x: x>60,l1)) # <filter object at 0x000002E5453CB278>
print(list(filter(lambda x: x>60,l1)))# [67, 78, 90]
#
lst = ['id':1,'name':'alex','age':50,
       'id':1,'name':'wusir','age':17,
        'id':1,'name':'taibai','age':16,]
print(list(filter(lambda x:x['age']<30,lst)))

# map 返回一个迭代器,相当于生成器表达式:循环模式
l1 = [56, 67, 12, 34, 78, 90,]
print([i**2 for i in l1])
print(map(lambda x:x**2,l1))
print(list(map(lambda x:x**2,l1)))

# reduce python3x 从内置函数剔除了。
作用是先把列表中的前俩个元素取出计算出一个值然后临时保存着,
接下来用这个临时保存的值和列表中第三个元素进行计算,求出一个新的值将最开始
临时保存的值覆盖掉,然后在用这个新的临时值和列表中第四个元素计算.依次类推
from functools import reduce # 引入模内置块
'''
第一次:x,y 1,2 求和 3 记录到内存
第二次:x,y 3,3 求和 6 记录到内存
第三次:x,y 6,4 .........

'''
# print(reduce(lambda x,y: x+y,[1,2,3,4,5]))
# print(reduce(lambda x,y: 2*x+y, [1,2,3]))
# print(reduce(lambda x,y: x+y, ['alex','s','b']))  # 可以用字符串拼接


闭包

什么是闭包:
    闭包是存在嵌套函数当中的,内层函数对外层函数的非全局变量的引用,这样就会产生闭包,引用的变量也就是自由变量,不会随着函数的结束而消失,会一直保存在内存中,最终的目的就是保证了数据的安全
闭包的形成条件:
    1.闭包存在于嵌套函数中
    2.内存函数对外层非全局变量引用(改变)
    (参考函数名逐层返回直至返回到最外层)
闭包:
    闭包函数的空间不会随着函数的结束而消失
    被引用的变量也不会消失
    被引用的变量叫自由变量
# 第一版: 没有保证数据的安全
l1 = []  #全局变量
def make_average(price):
    l1.append(price)
    total = sum(l1)
     return total/len(l1)
print(make_average(100000))
print(make_average(110000))
print(make_average(120000))

# 有很多代码....

# l1.append(666) 不小心输入个append就会是数据不准确
# print(make_average(90000))



# 第二版:
# 每次执行l1是空的。
def make_average(price):
    l1 = []
    l1.append(price)
    total = sum(l1)
    return total/len(l1)
print(make_average(100000))
print(make_average(110000))
print(make_average(120000))

# 为了保证数据的安全,闭包
def make_average():
    l1 = []
    def average(price):
        l1.append(price)
        total = sum(l1)
        return total/len(l1)
    return average
avg = make_average()
# print(avg)
print(avg(100000))
print(avg(110000))
print(avg(120000))
# print(globals())

def make_average():
     count = 1
    def average():
        nonlocal count
        count += 1
        return count
    return average
avg = make_average()
print(avg)
print(avg())
print(avg())
print(avg())
print(avg())





# 例一:
def wrapper():
    a = 1
    def inner():
        print(a)
    return inner
ret = wrapper()

# 例二:
a = 2
def wrapper():
    def inner():
        print(a)
    return inner
ret = wrapper()

# 例三:
def wrapper(a,b):
    def inner():
        print(a)
        print(b)
    return inner
a = 2
b = 3
ret = wrapper(a, b)

# 判断一个函数是不是闭包 == 闭包函数有没有自由变量
print(ret.__code__.co_freevars)


# 了解
print(ret.__code__.co_varnames)  # 函数中的局部变量

# 闭包的应用:
# 1,保证数据的安全。
# 2,装饰器的本质。

装饰器

1. 开放封闭原则

? 软件在制作时,不可能把所有功能都设计好,等上线后,后续按需求增加功能,定期迭代更新,对于软件之前写的源代码一般不会修改(函数里面的代码以及函数的调用方式)

开放原则 :在源码不改变的情况下,增加一些额外的功能

封闭原则 :不改变源码

python中的装饰器 :完美的诠释了开放封闭原则

装饰器 :装饰器就是一个函数,它要装饰一个函数,在不改变原函数的源代码以及调用方式的前提下,给其增加一些 额外的功能

2. 初识装饰器

# 1 李业,在一家xx科技有限公司工作,主管安排了一个任务,
# 写一个代码测试怼怼哥写的函数的执行效率。
import time
def index():
    time.sleep(2)
    print('欢迎访问博客园首页')
start_time = time.time()
index()
end_time = time.time()
print(f'此函数的执行效率end_time-start_time')
# 2. 主管让你测试小邓,李大象,重复代码太多。
def func1():
    time.sleep(2)
    print('欢迎访问日记首页')

def func2():
    time.sleep(1)
    print('欢迎访问评论首页')
  
start_time = time.time()
func1()
end_time = time.time()
print(f'此函数的执行效率end_time-start_time')

start_time = time.time()
func2()
end_time = time.time()
print(f'此函数的执行效率end_time-start_time')
# 3.  整合到函数中
def func1():
    time.sleep(2)
    print('欢迎访问日记首页')

def func2():
        time.sleep(1)
        print('欢迎访问评论首页')

def test_time(x):
    start_time = time.time()
    x()
    end_time = time.time()
print(f'此函数的执行效率end_time-start_time')

test_time(func1)
test_time(func2)
# 4. 怼怼哥这个函数在实际项目中被500执行,主管要求:在被执行此函数时,
# 同时要测试一下被执行函数的效率。

def index():
    time.sleep(2)
    print('欢迎访问博客园首页')
index()

def test_time(x):
    start_time = time.time()
    x()
    end_time = time.time()
    print(f'此函数的执行效率end_time-start_time')
test_time(index)
# 版本4的问题: 开放原则满足了,封闭原则:不改变原函数的源码,以及调用方式。
# 违反了封闭原则:改变了函数的调用方式。
# 版本5: 不能改变原函数的调用方式(闭包):

def index():
        time.sleep(2)
        print('欢迎访问博客园首页')
        index()
        
def func1():
    time.sleep(2)
    print('欢迎访问日记首页')
def test_time(x):  # x = index
        def inner():
        start_time = time.time()
        x()
        end_time = time.time()
        print(f'此函数的执行效率end_time-start_time')
        return inner

index = test_time(index)
index()
# 语法糖 @加上装饰器函数的名

def test_time(x):  # x = index
        def inner():
        start_time = time.time()
        x()
        end_time = time.time()
        print(f'此函数的执行效率end_time-start_time')
        return inner
  
@test_time  # index = test_time(index)
def index():
        time.sleep(2)
        print('欢迎访问博客园首页')
index()

@test_time
def func1():
        time.sleep(2)
        print('欢迎访问日记首页')
    
@test_time
def func2():
        time.sleep(1)
        print('欢迎访问评论首页')
 

func2 = test_time(func2)
func3 = test_time(func3)

# func2()

'''100行代码'''

# index()


'''10行代码'''

# index()

'''50行代码'''

# index()
# 版本6:被装饰函数有返回值

def test_time(x):  # x = index
        def inner():
        start_time = time.time()
        ret = x()
        end_time = time.time()
        print(f'此函数的执行效率end_time-start_time')
        return ret
return inner

@test_time  # index = test_time(index)
def index():
        time.sleep(0.5)
        print('欢迎访问博客园首页')
        return True
print(index())  # inner()

# 你应该是让True返回给index()这样才完美了,但是现在index是inner,所以你要是完全不改变原函数的使用,
# 你print(index()) ---> True
# 版本7: 被装饰函数带参数,无论加不加装饰器,你的实参'太白金星'应该传给形参n,。
# 但版本6不能实现传参,index('太白金星') ==  inner('太白金星')

def test_time(x):  # x = index
    def inner(*args,**kwargs):
        # 函数的定义:* ** 聚合。
        start_time = time.time()
        ret = x(*args,**kwargs)
        # 函数的执行:* ** 打散。
        end_time = time.time()
        print(f'此函数的执行效率end_time-start_time')
        return ret
    return inner
@test_time  # index = test_time(index)
def index(n):
    time.sleep(0.5)
    print(f'欢迎n访问博客园首页')
    return True

@test_time  # index = test_time(index)
def func2(a,b):
        time.sleep(0.5)
        print(f'最终结果:a+b')
        return a + b
print(index('苹果'))  # inner('苹果')
print(func2(1,3)) # == inner(1,3)


def warpper(f):
        def inner(*args,**kwargs):
        '''被装饰函数之前的操作'''
        # print(666)
        ret = f(*args,**kwargs)
        '''被装饰函数之后的操作'''
        # print('执行完毕了')
        return ret
return inner

@warpper
def func():
        print(111)

func()
func()
func()


# 装饰器的应用:在不改变原函数的源码以及调用方式前提下,为其增加额外的功能。
# 登陆认证,打印日志等。

装饰器的标准写法

##装饰器标准写法
def test_(func):
    def inner(*args,**kwargs):
        '执行被装饰函数之前的操作'
        ret = func(*args,**kwargs)
        """执行被装饰函数之后的操作"""
        return ret
    return inner
#登录构架
flag = False
def auth(f):
    def inner(*args,**kwargs):
        if flag:
            '''被装饰函数之前的操作'''
            # 登陆认证:
            # 输入用户名,输入密码
            ret = f(*args,**kwargs)
            '''被装饰函数之后的操作'''
            return ret
        else:
            pass
    return inner


@auth
def article():
    print('欢迎访问文章页面')

@auth
def diary():
    print('欢迎访问日记页面')
    
@auth
def comment():
    print('欢迎访问评论页面')

article()
diary()
comment()

3. 带参数的装饰器

def wrapper(f):
    def inner(*args,**kwargs):
        if f._name_ =='qq':
            ret = f(*args,*kwargs)
            return ret
        else:
            pass
    return inner


def wrapper(f):
    def inner(*args, **kwargs):
        ret = f(*args, **kwargs)
        return ret
    return inner


def wrapper_out(n,*args,sex='男',):
    def wrapper(f):  # f
        def inner(*args,**kwargs):
            ret = f(*args,**kwargs)  # func1()
            return ret
        return inner
    return wrapper

func = wrapper_out(1)  # wrapper函数名
ly = func(func1)  # wrapper(func1) = inner
ly()  # inner()



def wrapper_out(n):
    def wrapper(f):
        def inner(*args,**kwargs):
            # if n == 'qq':
            #     username = input('请输入用户名:').strip()
            #     password = input('请输入密码:').strip()
            #     with open('qq',encoding='utf-8') as f1:
            #         for line in f1:
            #             user,pwd = line.strip().split('|')
            #             if username == user and password == pwd:
            #                 print('登陆成功')
            #                 ret = f(*args,**kwargs)
            #                 return ret
            #         return False
            # elif n == 'tiktok':
            #     username = input('请输入用户名:').strip()
            #     password = input('请输入密码:').strip()
            #     with open('tiktok', encoding='utf-8') as f1:
            #         for line in f1:
            #             user, pwd = line.strip().split('|')
            #             if username == user and password == pwd:
            #                 print('登陆成功')
            #                 ret = f(*args, **kwargs)
            #                 return ret
            #         return False
            username = input('请输入用户名:').strip()
            password = input('请输入密码:').strip()
            with open(n,encoding='utf-8') as f1:
                for line in f1:
                    user,pwd = line.strip().split('|')
                    if username == user and password == pwd:
                        print('登陆成功')
                        ret = f(*args,**kwargs)
                        return ret
                return False
        return inner
    return wrapper



@wrapper_out('qq')
def qq():
    print('成功访问qq')
qq()
# # 看到带参数的装饰器分两步执行:
# @wrapper_out('腾讯')
#     1. 执行wrapper_out('腾讯') 这个函数,把相应的参数'腾讯' 传给 n,并且得到返回值 wrapper函数名。
#     2. 将@与wrapper结合,得到我们之前熟悉的标准版的装饰器按照装饰器的执行流程执行。
@wrapper_out('qq')
def qq():
    print('成功访问qq')

@wrapper_out('tiktok')
def tiktok():
    print('成功访问抖音')

qq()
tiktok()
# 开发思路:增强耦合性

4. 多个装饰器装饰一个函数

针对@ -→ 
装饰函数之前依次从上到下执结果输出, 
执行函数
装饰函数之后依次从后往前结果输出
def wrapper1(func1):  # func1 = f原函数
    def inner1():
        print('wrapper1 ,before func')  # 2
        func1()
        print('wrapper1 ,after func')  # 4
    return inner


def wrapper2(func2):  # func2 == inner1
    def inner2():
        print('wrapper2 ,before func')  # 1
        func2()  # inner1
        print('wrapper2 ,after func')  # 5
    return inner2


@wrapper2  # f = wrapper2(f) 里面的f == inner1  外面的f == inner2
@wrapper1  # f = wrapper1(f) 里面的f == func1  外面的 f == inner1
def f():
    print('in f')  # 3
f()  # inner2()

5. 递归函数

#  初识递归。
def func():
    print('in func')
def func1():
    func()
func1()


#比如:
def func():
    print(666)
    func()
func()


def func(n):
    print(n)
    n += 1
    func(n)
func(1)


# 官网规定:默认递归的最大深度1000次。
# 如果你递归超过100次还没有解决这个问题,那么执意使用递归,效率很低。
import sys
print(sys.setrecursionlimit(1000000))
def func(n):
    print(n)
    n += 1
    func(n)
func(1)


1  太白   18
2  景女神  18 + 2
3  宝元    18 + 2 + 2
4  alex    18 + 2+ 2+2  age(4) = age(3) + 2

def age(n):
    if n == 1:
        return 18
    else:
        return age(n-1) + 2
print(age(4))



def age(4):
    if n == 1:
        return 18
    else:
        return age(3) + 2
age(4) = age(3)  + 2



def age(3):
    if n == 1:
        return 18
    else:
        return age(2) + 2
age(4) = age(2) + 2  + 2



def age(2):
    if n == 1:
        return 18
    else:
        return age(1) + 2
age(4) = age(1) + 2 + 2  + 2    



def age(1):
    if n == 1:
        return 18
    else:
        return age(1) + 2
age(4) = 18 + 2 + 2  + 2    

'''



l1 = [1, 3, 5, ['太白','元宝', 34, [33, 55, [11,33]]], [77, 88],66]
1
3
5
'太白'
'元宝'
34
66

l1 = [1,3,5,['太白','元宝',34],55]
l2 = [1, 3, 5, ['太白','元宝', 34, [33, 55, [11,33]]], [77, 88],66]
for i in l1:
    if type(i) == list:
        for j in i:
            print(j)
    else:
         print(i)



def func(alist):
    for i in alist:
        if type(i) == list:
            func(i)  # func(['太白','元宝',34])
        else:
            print(i)
func(l1)
func(l2)

模块

1. 模块的定义与分类

什么是模块 : 一个py文件就是一个文件

模拟博客园系统作业,100000行代码. 不可能全部存在一个文件.

  1. 不易维护.
  2. 效率低.

分文件: 10个文件.每个文件有50个函数,有一写相同功能或者相似功能的函数.代码冗余,重复性.我们应该将这10个函数提取出来,放在一个文件中,随用随拿.

  1. 节省代码.
  2. 容易维护,组织结构更清晰.

一个模块就是一个py文件,这个模块存储很多相似的功能,相似的函数的集合体.

模块的分类:

  • 内置模块,标准库.python解释器自带的,time,os,sys,等等.200多种.
  • 第三方库(模块),各种大神写的一些模块,通过pip install....安装.6000种.
  • 自己写的模块.自定义模块.

2. import

# import tbjx
# # 当我引用tbjx模块的时候,实际上将tbjx.py执行一遍,加载到内存.
# import tbjx
# import tbjx
# import tbjx
# import tbjx
# import tbjx

# 只是第一次引用时,将此模块加载到内存.
  • 执行文件:02 模块import
  • 被引用文件(模块): tbjx.py

第一次导入模块发生的三件事

import tbjx
n = 1
# 引用模块发生三件事.
'''
    1. 将tbjx.py文件加载到内存.
    2. 在内存中创建一个以tbjx命名的名称空间.
    3. 通过tbjx名称空间的名字.等方式引用此模块的名字(变量,函数名,类名等等).
'''

# print(tbjx.name)
# tbjx.read1()
# tbjx.read2()

3. 被导入模块有独立的名称空间

# 坑:通过tbjx.的方式引用此模块的名字时,一定一定是从此模块中寻找.
# 通过import 引用模块 他有自己的独立名称空间,与当前执行文件没有关系.
name = '李业'
print(tbjx.name)

def read1():
    print('in 02 模块import')

tbjx.read1()

4. 为模块起别名

# 起别名:将一个比较长的模块名化简成简单的.
# import contextlib as cb
# 1 书写方便.
# import tbjx as tb
# print(tb.name)
# tb.read1()
# 2 简化代码.

5. 导入多个模块

# import time,os,sys  # 不推荐.
import time
import os
import sys

# 易于阅读 易于编辑 易于搜索 易于维护。

6. from... import...

# from tbjx import name
# from tbjx import read1
# print(globals())
# 相当于从tbjx模块的全局空间中将name,read1变量与值的对应关系
# 复制到当前执行文件的全局名称空间中.
# print(name)
# read1()

# 优点:使用起来方便了.
# 缺点:容易与当前执行文件产生覆盖效果.

7. from... import...的使用

# 示例1:
# from tbjx import name
# from tbjx import read1
# name = '李业'
# print(name)

# 示例2:
# name = '怼怼哥'
# from tbjx import name
# from tbjx import read1
# def read1():
#     print('在执行文件中')
# # print(name)
# read1()

# 特殊情况:极值情况,工作中不会出现.(了解)
# 因为如果你要是引用一些模块的变量,那么执行文件中就不应该出现同名变量.
# 示例3:
# from tbjx import name
# from tbjx import change
#
# change()
# print(name)

# 示例4:
# from tbjx import change
#
# change()
# from tbjx import name
# print(name)

# 也可以起别名
# from tbjx import name as n
#
# print(n)

一行导入多个

# 导入多个名字
# from tbjx import name
# from tbjx import read1

# from ... import *  尽量别单独用
# from tbjx import *
# print(name)
# read1()
# read2()
# 1,全部将tbjx的所有名字复制过来,无用功.
# 2,容易覆盖.

8. from... import *

from   模块名  import  引用的函数或其他
 
from ...import * 与__all__配合使用(写在模块开头写上:_all_ = ['引用变量名1','引用变量名2'])
 
# from tbjx import *
#
# # read1()
# # read2()
# change()

9. py文件的两种功能

  1. py文件的第一个功能:执行文件(承载代码) 脚本.

    直接打印__name__返回__main__

    调试模块:

    if _name_==‘_main_‘:

    ? 被调试的函数

    这样,被调试的函数只会在本py文件中执行,当被当做模块调用的时候不会执行

  2. py文件的第二个功能: 模块(被执行文件).

    直接打印__name__返回tbjx 模块名

作用:用来控制.py文件在不同的应用场景下执行不同的逻辑(或者是在模块文件中测试代码)

# import tbjx
# import time
# print(time.time())
# # import tbjx
# # tbjx.read1()
# import tbjx1
# tbjx1.read1()

10. 模块的搜索路径

# 寻找模块的路径: 内存 ----> 内置模块  ---> sys.path中找
# 只要这三个地方:内存 内置模块 sys.path可以找到这个引用的模块的路径,这个模块就可以直接引用到.
# import sys
# # print(sys.path)
# # import tbjx
# print(sys.modules)

# 如何引用到tbjx1.py
import sys
# print(sys.path) -- 是一个列表
sys.path.append(r'D:\s23\day15')
# import tbjx
import tbjx1
tbjx1.read1()

序列化模块

序列化模块 :将一个数据结构 ( list,dict… ) 转换成一个特殊的序列( 特殊的字符串 )的过程

# l1 = [1, 2, 3]
# ret = str(l1)
# print(ret,type(ret))
# print(eval(ret))  # 不让用

# 文件存取时,遇到的矛盾.
# dic ='username': '太白', 'password': 123

# dic = 1: 'username': '太白', 'password': 123,'status': False,
#        2:'username': 'alex', 'password': 123,'status': False

# 这个字典能放在全局么? (不可以,当数据多的时候,加载消耗时间)
# with open('register.json',encoding='utf-8',mode='w') as f1:
#     f1.write(str(dic))
# with open('register',encoding='utf-8') as f1:
#     ret = f1.read()
#     print(ret,type(ret))
#
# # 数据结构 --- > str() 存储在文件, 读取出来时,反转不回去.
# # 网络传输.
# l1 = [i for i in range(100000)]
# # 凡是数据通过网络传出去最终的格式必须bytes
# s1 = str(l1)
# b1 = s1.encode('utf-8')
# print(b1)  # b1可以发送出去
#
# s2 = b1.decode('utf-8')
# print(s2,type(s2))
# s2 转化不成列表了.

# 我们现在要解决的问题: 如果有一种特殊的字符串,这个字符串可以与任何的数据结构互相转换.

1. 序列换模块

# 序列化模块: 将一中数据结构转化成特殊的序列(特殊的字符串,bytes)并且还可以反转回去.

    # json模块: 是所有语言公认的一种序列.最最常用的
    #所以支持的python数据结构有限: int str bool dict list(tuple),None,float

    # None  ---> Null ----> NUll
    # dict  --->
    # pickle模块: 只能python语言中使用的,序列化模块:
    # 支持python所有的数据类型以及对象.
    # shevle模块(不讲): 课下了解(只能是文件存取).

2. json序列化

json序列换化--是所有语言公认的一种序列.最最常用的

两对 四个 方法:

dumps,loads 主要用于网络传输,可以用于文件的读取

import json
# dumps,loads 主要用于网络传输,可以用于文件的存取.
dic = 'username': '太白', 'password': 123,'status': False
ret = json.dumps(dic) # 转换成特殊的字符串供网络传输
print(ret,type(ret))
\\"username": "\u592a\u767d", "password": 123, "status": false <class 'str'>

ret_dict = json.load # 转换成源数据类型
print(ret_dict)
\\'username': '太白', 'password': 123, 'status': False

# 特殊的参数
dic = 'username': '太白', 'password': 123,'status': False
ret = json.dumps(dic,ensure_ascii=False,sort_keys=True) #ensuir_ascii 解决中文 sork_key 排序
print(ret,type(ret))
\\"password": 123, "status": false, "username": "太白" <class 'str'>

# 文件的读取
import json
dic = 'username': '太白', 'password': 123,'status': False
s_dict = json.dumps(dic)
with open('jsonlx.json',encoding='utf-8',mode='w') as f1:
     f1.write(s_dict)

with open('jsonlx.json',encoding='utf-8') as f2:
     content = f2.read()
     print(json.loads(content))

多个数据如何储存到一个文件中

#错误演示:
import json
dic1 = 'username': '太白', 'password': 123,'status': False
dic2 = 'username': 'alex', 'password': 123,'status': False
dic3 = 'username': 'ly', 'password': 123,'status': False
with open('jsonmore.json',encoding='utf-8',mode='a') as f1:
    # f1.write(json.dumps(dic1))
    # f1.write(json.dumps(dic2))
    # f1.write(json.dumps(dic3))
    f1.write(f'json.dumps(dic1)json.dumps(dic2)json.dumps(dic3)')

with open('jsonmore.json',encoding='utf-8') as f2:
    ret = json.loads(f2.read())
    print(ret)

          
# 正确做法:
import json
dic1 = 'username': '太白', 'password': 123,'status': False
dic2 = 'username': 'alex', 'password': 123,'status': False
dic3 = 'username': 'ly', 'password': 123,'status': False
with open('jsonmore.json',encoding='utf-8',mode='a') as f1:
    f1.write(f'json.dumps(dic1)\njson.dumps(dic2)\njson.dumps(dic3)')

with open('jsonmore.json',encoding='utf-8') as f1:
    for line in f1:
        ret = json.loads(line)
        print(ret,type(ret))

3. pickle序列化

pickle序列化, 只支持python

dumps,loads 只能是网络传输

#dumps,loads  只能是网络传输

import picklimport picklxe
l1 = ['wusir', '太白', '小黑', 666]
ret = pickle.dumps(l1)
print(ret)

l2 = pickle.loads(ret)
print(l2,type(l2))

dump load 数据结构存取文件.

import pickle
l1 = ['wusir', '太白', '小黑', 666]
with open('pickle练习.pickle',mode='wb') as f1:
    pickle.dump(l1,f1)

with open('pickle练习.pickle', mode='rb') as f1:
    ret = pickle.load(f1)
    print(ret,type(ret))

# 多个数据写入文件
l1 = ['wusir', '太白', '小黑1', 666]
l2 = ['wusir', '太白', '小黑2', 666]
l3 = ['wusir', '太白', '小黑3', 666]
with open('pickle练习1.pickle',mode='wb') as f1:
     pickle.dump(l1,f1)
     pickle.dump(l2,f1)
     pickle.dump(l3,f1)

with open('pickle练习1.pickle', mode='rb') as f1:
    ret1 = pickle.load(f1)
    ret2 = pickle.load(f1)
    ret3 = pickle.load(f1)
    print(ret1,ret2,ret3)

os模块

import os

print(os.getcwd()) 获取当前文件的绝对路径
os.chdir('路径')  修改当前的工作路径  shell下cd  **
os.chdir 返回文件??目录 os.chdir('.')当前  os.chdir('..')上一级(父级)

#与文件夹相关
os.makedirs('文件夹3/文件夹2/文件夹1') # 生成递归文件夹 ***
os.removedirs('文件夹3/文件夹2/文件夹1')
# 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 ***

os.mkdir('文件夹')  # 生成单级目录;相当于shell中mkdir dirname ***
os.rmdir('文件夹') # 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname ***
print(os.listdir('文件夹'))#列出指定目录下的所有文件和目录,包括隐藏文件,并以列表方式打印 **

# 和文件相关
os.remove()  删除一个文件  ***
os.rename("oldname","newname")  重命名文件/目录  ***
print(os.stat('练习.py')) 获取文件/目录信息 **

"""
stat 结构:
st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
"""

# 和操作系统差异相关
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/" *
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n" *
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为: *
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix' *
#和执行系统命令相关
os.system("bash command")  运行shell命令,直接显示  **
os.popen("bash command).read()  运行shell命令,获取执行结果  **
os.environ  获取系统环境变量  **

#path系列,和路径相关
print(os.path.abspath('练习.py')) #返回path规范化的绝对路径  ***
os.path.split(path) #将path分割成目录和文件名二元组返回 ***
os.path.dirname(path) #返回path的目录。其实就是os.path.split(path)的第一个元素  **
os.path.basename(path) 
#返回path最后的文件名。如何path以/或\结尾,那么就会返回空值,即os.path.split(path)的第二个元素。 **
         
os.path.exists(path)  # 如果path存在,返回True;如果path不存在,返回False  ***
os.path.isabs(path)  # 如果path是绝对路径,返回True  **
os.path.isfile(path)  # 如果path是一个存在的文件,返回True。否则返回False  ***
os.path.isdir(path) # 如果path是一个存在的目录,则返回True。否则返回False  ***
os.path.join(path1[, path2[, ...]])  #将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 ***
  $路径的拼接:
# path = r'D:\s23\day17\db\lydata'
# path = par_dir + '\db' +'\lydata'
# path = os.path.join(par_dir,'db','lydata')
os.path.getatime(path) # 返回path所指向的文件或者目录的最后访问时间  **
os.path.getmtime(path)  # 返回path所指向的文件或者目录的最后修改时间  **
os.path.getsize(path) # 返回path的大小 ***

sys模块

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version        获取Python解释程序的版本信息
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值  ***
sys.platform       返回操作系统平台名称

hashlib模块

叫法 : 摘要算法 , 加密算法 , 哈希算法 , 散列算法

作用 : 加密和校验

工作原理 : 通过函数,把任意长度的数据按一定规则转换为一个固定长度的数据串通常用16进制的字符串表示)。

hashlib的特征及使用要点 :

  • bytes类型数据 ---> 通过hashlib算法 ---> 固定长度的字符串
  • 不同的bytes类型数据转化成的结果一定不同。
  • 相同的bytes类型数据转化成的结果一定相同。
  • 此转化过程不可逆。

1. md5 - 密码加密

import hashlib  # 引入模块
ret = hashlib.md5() # 创建一个用来装数据的容器
ret.update('123'.encode('utf-8')) # 把需要加密的数据放到容器
s = ret.hexdigest() # 封装容器
print(s)

#撞库 : 一些简单的密码如1111, 1234 6666 8888 等,
ret = hashlib.md5()
ret.update('123456*@qwe'.encode('utf-8'))
s = ret.hexdigest()
print(s,type(s))

# 加固定盐
ret = hashlib.md5('xxx教育'.encode('utf-8'))
ret.update('123456'.encode('utf-8'))
s = ret.hexdigest()
print(s,type(s))

# 加动态的盐
username = input('输入用户名:').strip()
password = input('输入密码').strip()
ret = hashlib.md5(username[::2].encode('utf-8'))
ret.update(password.encode('utf-8'))
s = ret.hexdigest()
print(s)

# sha系列: 安全系数高,耗时高.
# 加盐,加动态盐
ret = hashlib.sha512()
ret.update('123456fdklsajflsdfjsdlkafjafkl'.encode('utf-8'))
s = ret.hexdigest()
print(s,type(s))

2. 文件的一致性校验

# low版
import hashlib
ret = hashlib.md5()
with open('MD5文件校验',mode='rb') as f1:
    content = f1.read() # 占内存,若校验的文件过大,系统内存会溢出
    ret.update(content)
print(ret.hexdigest())

# 分步update
s1 = '老男孩教育 最好的python 讲师 是 太白'
# # 1
ret = hashlib.md5()
ret.update(s1.encode('utf-8'))
print(ret.hexdigest()) #90c56d265a363292ec70c7074798c913
# # 2
ret = hashlib.md5()
ret.update('老男孩教育'.encode('utf-8'))
ret.update(' 最好的python'.encode('utf-8'))
ret.update(' 讲师 是'.encode('utf-8'))
ret.update(' 太白'.encode('utf-8'))
print(ret.hexdigest())  # 90c56d265a363292ec70c7074798c913



# 高大上版
import hashlib
def md5_file(path):
    ret = hashlib.md5()
    with open(path,mode='rb') as f1:
        while 1:
            content = f1.read(1024) # 每次读取1024个字符,节省内存
            if content:
                ret.update(content)
            else:
                return ret.hexdigest()

print(md5_file(r'D:\s23\day17\python-3.7.4rc1-embed-win32.zip'))

规范化开发

目录结构

????项目 - 项目的总文件夹

? ????bin

? ??starts.py - 程序的启动 (为了防止误输入和其他等 在starts.py中加入if _name_ == ‘_main_‘: 后面 加上调用程序开始执行的函数)

? import sys

? import os

? BASE_PATH = os.path.dirname(os.path.dirname(_file_))

? sys.path.append(BASE_PATH)

? from … import 模块

? ????conf ( config )

? ??settings.py - 存放一些配置文件 ( 静态变量 - 轻易不改变的变量 )

? ????core -

? ??src.py - 放主逻辑

? ????db -

? ??register.py - 数据库文件,注册表,用户信息,访问记录等

? ????lib -

? ??common.py - 公共组件部分,装饰器等

? ????log

? ??access.py

? ??README - 描述项目的信息

time模块

1. 格式化时间

imoprt time #导入时间模块
time.time() # 时间戳
# 时间字符串
time.strftime("%Y-%m-%d %X") # 需要打印  Y 大写表示年份写全,如2019  小写则为19
\\2019-06-28 15:43:32

time.strftime("%Y-%m-%d %H-%M-%S") # 需要打印
\\2019-06-28 15-44-14

print(time.strftime("%Y%m%d %H:%M:%S").format('年','月','日'))
\\2019年06月28日 15:45:43

2. 时间戳与结构化时间的相互转换

时间戳 ---→ 结构化时间
import time
t1= time.strftime('%Y/%m/%d %H:%M:%S') # 格式化时间 \\t1= 2019/06/28 15:52:08
t2= time.strptime(t1,'%Y/%m/%d %H:%M:%S') # 结构化时间
print:
time.struct_time(tm_year=2019, tm_mon=6, tm_mday=28, tm_hour=15, tm_min=56, tm_sec=59, tm_wday=4, tm_yday=179, tm_isdst=-1)

结构化时间 -- → 时间戳
t3 =time.mktime(t2) # \\1561708758.0  只保留一位小数

结构化时间 --→ 格式化时间
t4 = time.strftime('%Y/%m/%d %H:%M:%S',t2) #\\2019/06/28 16:03:20

datetime模块

import datetime
now_time = datetime.datetime.now()  # 现在的时间
# 只能调整的字段:weeks days hours minutes seconds
print(datetime.datetime.now() + datetime.timedelta(weeks=3)) # 三周后
print(datetime.datetime.now() + datetime.timedelta(weeks=-3)) # 三周前
print(datetime.datetime.now() + datetime.timedelta(days=-3)) # 三天前
print(datetime.datetime.now() + datetime.timedelta(days=3)) # 三天后
print(datetime.datetime.now() + datetime.timedelta(hours=5)) # 5小时后
print(datetime.datetime.now() + datetime.timedelta(hours=-5)) # 5小时前
print(datetime.datetime.now() + datetime.timedelta(minutes=-15)) # 15分钟前
print(datetime.datetime.now() + datetime.timedelta(minutes=15)) # 15分钟后
print(datetime.datetime.now() + datetime.timedelta(seconds=-70)) # 70秒前
print(datetime.datetime.now() + datetime.timedelta(seconds=70)) # 70秒后

current_time = datetime.datetime.now()
# 可直接调整到指定的 年 月 日 时 分 秒 等

print(current_time.replace(year=1977))  # 直接调整到1977年
print(current_time.replace(month=1))  # 直接调整到1月份
print(current_time.replace(year=1989,month=4,day=25))  # 1989-04-25 18:49:05.898601

# 将时间戳转化成时间
print(datetime.date.fromtimestamp(1232132131))  # 2009-01-17

random 模块

1. random的使用

>>> import random
#随机小数
>>> random.random()      # 大于0且小于1之间的小数
0.7664338663654585
>>> random.uniform(1,3) #大于1小于3的小数
1.6270147180533838
#恒富:发红包

#随机整数
>>> random.randint(1,5)  # 大于等于1且小于等于5之间的整数
>>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数


#随机选择一个返回
>>> random.choice([1,'23',[4,5]])  # #1或者23或者[4,5]
#随机选择多个返回,返回的个数为函数的第二个参数
>>> random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合
[[4, 5], '23']


#打乱列表顺序
>>> item=[1,3,5,7,9]
>>> random.shuffle(item) # 打乱次序
>>> item
[5, 1, 3, 7, 9]
>>> random.shuffle(item)
>>> item
[5, 9, 7, 1, 3]

2. 生成随机验证码

import random

def v_code():

    code = ''
    for i in range(5):
        num=random.randint(0,9)
        alf=chr(random.randint(65,90))
        add=random.choice([num,alf])
        code="".join([code,str(add)])

    return code

print(v_code())
生成随机验证码

以上是关于Python基础2的主要内容,如果未能解决你的问题,请参考以下文章

Python数据分析基础-2Python标量类型

学习笔记2Python - Jupyter Notebook界面基础

Python基础点记录1

Python 第一课 pyhon基础

python基础--环境的安装

scrapy基础