• Python全栈开发记录_第四篇(集合、函数等知识点)


    知识点1:深拷贝和浅拷贝

    • 非拷贝(=赋值:数据完全共享,内存地址一样,修改一个另一个也变化)
    • 浅拷贝:数据半共享(复制其数据独立内存存放,但是只拷贝成功第一层)像[[1,2],3,4]如果修改列表中列表[1,2]的值则会一起修改
    • 深拷贝:数据完全不共享(复制其数据完完全全放独立的一个内存,完全拷贝,数据不共享)

    知识点2:set集合

    • 去重功能,集合本身无序、不重复,所以不能通过索引和键进行取值,集合对象是无序可哈希(不可改变)的值(也就是说对于set([[1,2],3,4])是不行的,因为列表里面中还包含了列表(可改变的值),所以会出现set失败)
    • 空集合(set()),而{}是字典,集合分可变和不可变(frozenset),一般我们说的都是可变的,由于可变,所以set()本身就是不可哈希的,因此不能作为字典的key
    • 创建集合:set("liu")就是{'l', 'i', 'u'}且类型为set,注意虽然是大括号但是不是字典类型
    • 访问集合:由于集合本身的无序,所以不能使用索引、切片等访问,只能通过循环遍历访问或者in not in去判断是否是集合元素
    • 集合添加元素:add方法和update,详情如下
    • s = set("liu")
      s.add("ta") #添加一个元素'ta'
      s.update("za")  #添加两个元素,'z'和'a'
      s.update(["34","12"]) #添加两个元素'34'和'12' 
      
      print(s)
      结果:
      {'ta', 'l', 'u', 'a', '12', 'z', 'i', '34'}
    • 集合元素删除:remove(元素)删除指定元素,pop()随机删除集合元素,s.clear()清空集合元素,剩下一个空集合,del s(删除集合,删除后s就不存在了)
    • 集合类型操作:
    s1 = {"a", "b", "c"}
    s2 = {"c", "d", "e"}
     
    # 交集
    # 两个集合中的共有元素
    print(s1 & s2)  # {'c'}
    print(s1.intersection(s2))  # {'c'}
     
    # 并集(联合)
    print(s1 | s2)  # {'e', 'd', 'b', 'a', 'c'}
    print(s1.union(s2))  # {'e', 'd', 'b', 'a', 'c'}
     
    # 差集
    print(s1 - s2)  # {'a', 'b'}
    print(s1.difference(s2))  # {'a', 'b'}
     
    # 反交集(对称差集)
    print(s1 ^ s2)  # 两个集合中单独存在的数据 {'e', 'a', 'd', 'b'}
    print(s1.symmetric_difference(s2))  # 两个集合中单独存在的数据 {'e', 'a', 'd', 'b'}
     
     
    s1 = {"a", "b"}
    s2 = {"a", "b", "c"}
     
    # 子集
    print(s1 < s2) # set1是set2的子集吗? True
    print(s1.issubset(s2))
    # 超集(父级)
    print(s1 > s2) # set1是set2的超集吗? False,s2是s1的超集
    print(s1.issuperset(s2))

    知识点3:函数

    • 必需参数(以正确的顺序传入函数。调用时的数量必须和声明时的一样。类似f(name, age),传入的时候这样f("liu", 18)
    • 关键字参数(使用关键字参数允许函数调用时参数的顺序与声明时不一致。类似f(name, age),传入的时候这样f(age=18, name="liu")
    • 缺省参数(调用函数时,缺省参数的值如果没有传入,则被认为是默认值。类似f(name, age = 18),传入的时候这样f(name="liu"),而age为默认参数
    • 不定长参数(加了星号(*)的变量名会存放所有未命名的变量参数。而加(**)的变量名会存放命名的变量参数,*args会将参数存成元祖,**kwargs会将参数存放成字典) 

    1、总结四种参数位置优先级:必需参数和关键字参数放最左边,缺省(默认参数)第二位,不定长参数放第三位(**args放在左边,**kwargs参数放在右边)

    2、函数注意点:

    1. 函数内没有return,默认返回None
    2. 如果return多个对象,python会自动帮我们将多个对象封装成元祖返回
    3. test(*args)中* 的作用其实就是把序列 args 中的每个元素,当作位置参数传进去。比如上面这个代码,如果 args 等于 (1,2,3) ,那么这个代码就等价于 test(1, 2, 3) 
    4. test(**kwargs)中** 的作用则是把字典 kwargs 变成关键字参数传递。比如上面这个代码,如果 kwargs 等于 {'a':1,'b':2,'c':3} ,那这个代码就等价于 test(a=1,b=2,c=3) 

    3、python中的作用域分4种情况:

    • L:local,局部作用域,即函数中定义的变量;
    • E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
    • G:globa,全局变量,就是模块级别定义的变量;
    • B:built-in,系统固定模块里面的变量,比如int, bytearray等。 搜索变量的优先级顺序依次是:局部作用域>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB

    当内部作用域想修改外部作用域的变量时,就要用到globalnonlocal关键字了,当修改的变量是在全局作用域(global作用域)上的,就要使用global先声明一下,而nonlocal关键字是修改嵌套作用域(enclosing作用域,外层非全局作用域)

    4、函数小结: 

    (1)变量查找顺序:LEGB,局部作用域>外层作用域>当前模块中的全局>python内置作用域;

    (2)只有模块、类、及函数才能引入新作用域;

    (3)对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量;

    (4)内部作用域要修改外部作用域变量的值时,全局变量要使用global关键字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个 关键字,就能完美的实现闭包了。 

    一个有趣的函数例子:

    def outer():
        def inner():
            return 1
        return inner  #返回inner的内存地址
    a = outer        #将outer的内存地址赋值了给a
    print(a())      #相当于outer(),结果实际上是返回了inner的内存地址
    print(a()())    #这里打印了结果1,因为执行了inner,所以返回了1

    5、函数的递归

    定义:在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

    其实函数的递归最典型的就是斐波那契数列(1、1、2、3、5、8.。。),下面是这个的例子

    u'''斐波那契数列(1、1、2、3、5、8.。。)'''
    #第一种:循环方式实现
    def feibo1(n):
        if n <= 1:
            return n
        first_num = 0
        second_num = 1
        for i in range(n-1):
            sum1 = first_num + second_num
            first_num = second_num
            second_num = sum1
        return sum1
    
    #第二种:递归方式实现
    def feibo2(n):
        if n <= 1:
            return n
        return feibo2(n-1) + feibo2(n-2)

    递归函数的优点:    是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

    递归特性:

    1. 必须有一个明确的结束条件

    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。)

    6、重要的内置函数

           1 filter(function, sequence)     对sequence中的item依次执行function(item),将执行结果为True的item做成一个filter object的迭代器返回。可以看作是过滤函数。

    list1 = [1, 2, 3, 4]
    
    def fun(str1):
        if str1 != 3:
            return str1
    
    result = filter(fun, list1)    #主要是过滤作用,返回结果为True的值
    print(list(result))    -->结果是[1, 2, 4]

      2 map(function, sequence)       对sequence中的item依次执行function(item),将执行结果组成一个map object迭代器返回,当然map也支持多个sequence,这就要求function也支持相应数量的参数输入。

    list1 = ["a", "b", "c"]
    
    def fun1(str):
        return str + "test"
    
    result1 = map(fun1, list1)   #注意下面map和filter区别,如果没条件过滤,filter后还是返回本身
    result2 = filter(fun1, list1)
    print(list(result1))    #结果是['atest', 'btest', 'ctest']
    print(list(result2))    #结果是['a', 'b', 'c']
    def add1(x,y):    #多个sequence的情况
        return x+y
    print (list(map(add1, range(10), range(10))))##[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

      3 reduce(function, sequence, starting_value)     对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用.

    from functools import reduce
    
    
    def fun1(x, y):
        return x*y
    
    
    result = reduce(fun1, range(1, 6))   # 通过reduce就直接实现了阶乘,注意下,这里reduce的结果就是一个值而不是迭代器
    print(result)

      4 lambda 匿名函数

    像上面reduce实现的阶乘,这里通过匿名函数再实现,对比下两者:

    from functools import reduce
    result = reduce(lambda x, y: x*y, range(1, 6))   #匿名函数的命名规则,用lamdba 关键字标识,冒号(:)左侧表示函数接收的参数(x,y) ,冒号(:)右侧表示函数的返回值(x*y)
    print(result)
  • 相关阅读:
    day5 页面布局
    1、rbac权限组件-初识, 中间件校验1
    1 、算法-总结
    10 腾讯云、django2.0、uwsgi、mysql、nginx 部署
    9 README,全套代码
    8 功能6:后台管理页面,编辑文章,xss攻击
    3-面试篇-操作系统
    7 功能5:文章详情页、评论、评论树
    6 功能4:文章详情页、点赞功能
    2- 面试篇-数据库
  • 原文地址:https://www.cnblogs.com/leixiaobai/p/9876259.html
Copyright © 2020-2023  润新知