美文网首页
python:基础

python:基础

作者: alan2yang | 来源:发表于2019-02-22 23:23 被阅读2次

    自己以前整理的笔记,不太完整,后续会不断更新。。。。


    • [ ] LEGB规则
    • [ ] ​

    一、代码规范

    1.# 号注释时在其后跟一个空格,解释器遇到#号直接跳过,不运行

    2.代码短的情况下,可将注释放在代码后,但注释要与代码至少间隔2个空格

    3.''' '''多行注释/块注释,内容全部忽略

    4.代码注释不少越多越好,复杂的操作要加上若干行注释,不要描述代码

    5.PEP8对Python的代码格式给出了建议

    6.赋值语句=左右两边各保留一个空格

    7.变量命名:多个字母时用_连接,且都用小写字母--推荐

    8.另外一种命名规则--驼峰命名法:大驼峰、小驼峰

    9.代码中的缩进tab和空格不要混用

    10.模块命名要求与变量命名要求一致

    二、运行原理

    1. 程序运行完后为程序分配的内存空间清零,数据清除
    2. 主程序中变量名第一次出现才是定义变量,后续再次出现是直接使用变量
    3. 程序运行的三大流程:顺序,分支,循环

    三、变量

    01.变量的引用

    • 变量和数据是分开存储的
    • 数据保存在内存中某个位置,通过地址找到
    • 变量保存着数据在内存中的地址
    • 变量中记录数据的地址叫引用

    _xx:单前置下划线变量,当作为模块导入其他程序中时,该变量不可访问

    __xx:双前置下划线变量,私有属性或方法,子类无法继承和使用

    __xx__:前后双下划线,魔法方法或属性

    xx_:单后置下划线,用于避免与python关键词冲突

    变量作用域

    LEGB规则

    使用id( )函数可查看变量中所保存的数据的地址,十进制输出

    python中函数的 实参/返回值 都是是靠 引用 来传递来的

    02.可变类型数据和不可变类型数据

    • 不可变数据:数字、字符串、元组
    • 可变数据:列表、字典、集合

    Tips:

    1. 字典的key只能是不可变数据,内部进行了hash(key)运算,输入的key必须是不可变类型的数据
    2. 可变数据的内容变化通过方法实现
    3. 如果给一个可变数据类型的变量重新赋值相同类型的数据,引用会修改
    # 两个a的id不同
    
    a = [1,2]
    print(id(a))
    
    a = [1,2]
    print(id(a))
    
    # b,c的id相同
    b = 1
    print(id(b))
    
    c = 1
    print(id(c))
    

    03.局部变量和全局变量

    
    x = 1
    def func(x):
        print('x is ', x)
        x = 2
        print('local x is', x)
    
    func(x)
    print('global x is', x)
    
    # 输出
    # x is 1
    # local x is 2
    # global x is 1
    
    
    1. 全局变量
      为了保证所有的函数都能够正确使用到全局变量,应该 将全局变量定义在其他函数的上方
      全局变量 是在 函数外部定义 的变量(没有定义在某一个函数内),所有函数 内部 都可以使用这个变量,但不能使用=修改 ,可以使用方法进行修改

    若要在函数内修改全局变量,需要先对变量进行global声明 ,再进行重新赋值

    x = 1
    
    def func():
        # print(x)      # 用global 定义全局变量前不能调用,否则报错
        global x
        print('x is ', x)
        x = 2
        print('local x is', x)
    
    func()
    print('global x is', x)
    
    1. 局部变量
      函数执行结束后,函数内部的局部变量,会被系统回收
    • 若函数内的局部变量名与全局变量名相同,且进行了赋值操作,实质上是新建了一个变量,只不过和全局变量名相同而已
    • 其他注意事项见5-2

    局部变量的生命周期

    • 所谓 生命周期 就是变量从 被创建被系统回收 的过程
    • 局部变量函数执行时 才会被创建
    • 函数执行结束后 局部变量 被系统回收
    • 局部变量在生命周期 内,可以用来存储 函数内部临时使用到的数据

    注意
    函数执行时,需要用到变量时 会:

    1. 首先查找函数内部 是否存在 指定名称 的局部变量如果有,直接使用
    2. 如果没有,查找 函数外部 是否存在 指定名称 的全局变量如果有,直接使用
    3. 如果还没有,程序报错!

    全局变量与局部变量之间的一些注意事项:

    1. 在 global 中出现的名字不能在global 之前的代码中使用。
    2. 在 global 中出现的名字不能作为形参, 不能作为循环的控制对象, 不能在类定义, 函数定义, import语句中出现。
    hehe=6
    def f():
        print(hehe)        # 不能在赋值前调用  why?????
        hehe=2
    f()
    print(hehe)
    
    # 报错:UnboundLocalError: local variable 'hehe' referenced before assignment
    
    x = 1
    
    def func():
        print(x)      # 用global 定义全局变量前不能调用,否则报错   why?????????????
        global x
        print('x is ', x)
        x = 2
        print('local x is', x)
    
    func()
    
    # 报错:SyntaxError: name 'x' is used prior to global declaration
    

    四、循环

    1. 使用continue时要注意修改判断条件
    2. break和continue只对当前循环有效

    五、函数

    1. 封装
    2. 重用
    • 函数定义后不调用则不执行
    • 定义函数体上方应和其他代码(包括注释)保留两行空行

    函数中变量的生命周期????????

    5-1 函数参数类型

    1.缺省参数/默认参数

    • 一般放在形参列表的最后面
    • 定义函数时,位置参数要放在默认/缺省参数前,否则语法错误
    • 默认参数必须是不可变对象,若是可变对象则会出现问题

    如默认参数为列表、字典或大多数类的实例,函数在后续调用中会记录前面传递的参数

    
    def f(a, L = []):
        L.append(a)
        return L
    
    
    print(f(1))   # [1]
    print(f(2))   # [1,2]
    print(f(3))   # [1,2,3]
    
    # 改善方法
    def fun(a, li=None):
        if li is None:
            li = []
        li.append(a)
        return li
    
    

    默认参数在函数定义时就被解析,如下:

    i = 5
    
    def f(arg=i):
        print(arg)
    
    i = 6
    f()
    # 结果:
    # 5
    

    2.可变参数/多值参数/收集参数

    函数接收的参数个数不确定时,使用多值参数

    • 放在位置参数后,默认参数/关键字参数前
    • 若定义函数时,形参位置没有按照上条执行,也可通过关键字参数来赋值

    两种类型:

    1. 形参名前加*,接收为元组
      传入的数据被打包成元组,但不包含赋值映射对

    2. 形参名前加**,接收为字典
      将传入的key=value值打包成字典

    def demo1(num, *args, **kwargs):
        print(num)
        print(args)
        print(kwargs)
    
    demo1(1, 2, 3, 4, n=1, m=2, st='hello')
    
    # 运行结果
    # 1
    # (2, 3, 4)
    # {'n': 1, 'm': 2, 'st': 'hello'}
    

    拆包
    一个问题:若某变量中保存有一个列表或字典,该如何将其内容传入函数?

    def demo2(num, *args, **kwargs):
        print(num)
        print(args)
        print(kwargs)
    
    
    a = (1, 2, 3, 4)
    b = {'name': 'xm', 'age': 18}
    demo2(1, a, b)
    # a,b都传入了args中,kwargs为空
    # 1
    # ((1,2,3,4),{'name': 'xm', 'age': 18})
    # {}
    

    以上程序并没有达到预期,这时需要用到拆包:
    在对应的实参名前加上对应的*即可

    # 其效果类似于关键字参数,只不过是通过*来识别
    def demo3(num, *args, **kwargs):
        print(num)
        print(args)
        print(kwargs)
    
    
    a = [1, 2, 3, 4]
    b = {'name': 'xm', 'age': 18}
    demo3(1, *a, **b)
    # 1
    # (1,2,3,4)
    # {'name': 'xm', 'age': 18}
    

    总结:!!!!!!!
    以下结论也适用于**,只不过1.**后的数据类型对应的是映射对象(map),2.将映射对象保存在字典中

    def f(**a):
        print(a)
    
    f(m=1, n=2)
    # {'m':1,'n':2}
    

    所以,*和**其实可以起到过滤数据的作用,*后的数据类型必须是可迭代对象,**后的数据类型必须是映射对象;而当**kwargs作为形参接收数据时,可传入的数据类型必须是map对象,而*args没有限制。

    1.可迭代对象前加*的效果

    # *后跟可迭代对象,结果是将可迭代对象拆开为单个元素
    print(1, 2, 3)
    # 1 2 3
    print(*[])
    #
    print(*[1, 2, 3])
    # 1 2 3
    print(*())
    #
    print(*(1, 2, 3))
    # 1 2 3
    
    print(*'hello')
    print('h', 'e', 'l', 'l', 'o')
    # h e l l o
    
    print(*{'name': 'xm', 'age': 18})
    print('name', 'age')
    # name age
    
    print(*{1, 2, 3})
    # 1 2 3
    
    

    2.变量名前加*的效果

    # 无论传入的数据个数及类型,最终以元素保存在元组中,结合1中的例子理解
    def f(*a):
        print(a)
    
    f(1, 2)
    # (1,2)
    
    
    def f2(*b):
        print(b)
        
    f2((1, 2), [1, 2, 3], 1)
    # ((1,2),[1,2,3],1)
    
    
    def f3(*c):
        print(c)
    
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    x='hello'
    f3(*x)
    # ('h', 'e', 'l', 'l', 'o')
    
    # *-* coding:utf-8 *-*
    
    
    def test1(a, b, *args, **kwargs):
        print(a)
        print(b)
        print(args)
        print(kwargs)
    
    
    def test2(a, b, *args, **kwargs):
        print(a)
        print(b)
        print(args)
        print(kwargs)
        print('-------------')
        # test1(a, b, args, kwargs)  # args和kwargs是两个变量被打包进test1中的元组参数中
        test1(a, b, *args, **kwargs)  # 
    
    
    test2(1, 2, 3, 4, 5, 6, h='hello', t=1)
    

    3.关键字参数

    调用函数时,在函数括号中直接给形参赋值,不讲顺序
    当函数的形参有多个缺省参数时,可通过关键字参数进行赋值

    def mutable(name, action):
        print(name+'->'+action)
    
    
    mutable(action='change the world!', name='yl')
    

    5-2 函数参数与局部变量

    针对局部变量:

    • 无论传递的参数是可变还是不可变,只要在函数内部对参数使用 赋值语句=,会在函数内部 修改 局部变量的引用不会影响到外部变量的引用
    • 如果传递的参数是 可变类型,在函数内部,使用 方法 修改了数据的内容,就会影响到外部的数据
    • 可变类型变量调用+=效果等同于.extend( )方法
    def demo4(num, num_list):
        print('函数内部开始:')
        num += num
        # num = num + num     # 两种方式效果相同,num的id都有变化(数字是不可变对象,只能重新创建),全局变量数字不变
    
        num_list += num_list           # 列表id不变(列表是可变对象,在原来的基础上更改,效果等同于.extend()),改变全局变量列表
    
        # num_list = num_list + num_list  # 列表id变化(列表相加产生新的列表),相当于新建一个变量
    
        print(num)
        print(num_list)
        print('函数内部结束.')
    
    
    gl_num4 = 9
    gl_list = [1, 2, 3]
    demo4(gl_num4, gl_list)
    print(gl_num4, gl_list)
    
    def mutable(num_list):
        # num_list = [1, 2, 3]
        num_list.extend([1, 2, 3])  # => num_list += [1, 2, 3]
        
        print(num_list)
    
    
    gl_list = [6, 7, 8]
    mutable(gl_list)
    print(gl_list)
    
    # 结果
    # [6, 7, 8, 1, 2, 3]
    # [6, 7, 8, 1, 2, 3]
    

    5-3 递归

    函数调用自身的编程技巧

    • 递归要有出口,这个出口一般是满足一定条件时,不再调用函数
    • 递归要有返回值
      使用递归的一般方法:
    1. 从一般到特殊,从大概到具体,最后的出口一般是最小值
    2. 假设函数(n-1)的功能可以实现

    特点:
    每次递归都是重新调用函数,极耗内存

    相关文章

      网友评论

          本文标题:python:基础

          本文链接:https://www.haomeiwen.com/subject/nkzyyqtx.html