美文网首页
python常见错误2

python常见错误2

作者: Chaweys | 来源:发表于2021-01-28 00:04 被阅读0次

    #coding=utf-8
    
    #1、默认可变对象的赋值修改
    def addElement(a,list1=[]):
        list1.append(a)
        return list1
    
    print(addElement("菜鸟"))
    print(addElement("菜鸟学python"))
    '''
    ['菜鸟']
    ['菜鸟', '菜鸟学python']
    '''
    
    
    def addElement2(a,list1=""):
        list1=list1+a
        return list1
    print(addElement2("菜鸟"))
    print(addElement2("菜鸟学python"))
    '''
    菜鸟
    菜鸟学python
    '''
    
    '''
    总结:
    上述两个函数addElement()和addElement2()得出的结果不同:
    addElement():由于list1=[]属于python中的可变对象,因此只在函数被定义的时候才能被创建一次,所以在调用的时候都使用的创建好的同一个list列表
    addElement2():由于list1=""属于python中的不可变对象,所以被调用时每次都是新的开辟内存地址存储该不可变对象
    
    python不可变对象:int,string,float,tuple
    python可变对象:  dict,list
    '''
    
    
    
    #2、浅拷贝和深拷贝
    '''
    浅拷贝只拷贝了父对象,子对象仍然引用同一个
    深拷贝拷贝了父对象,子对象也一并拷贝
    '''
    import copy
    dict1={"1":"a","2":["b1","b2","b3"],"3":"c","4":"d"}
    dict2=copy.copy(dict1)
    dict3=copy.deepcopy(dict1)
    
    print("删除之前:")
    print(dict1)
    print(dict2)
    print(dict3)
    '''
    {'2': ['b1', 'b2', 'b3'], '3': 'c', '1': 'a', '4': 'd'}
    {'2': ['b1', 'b2', 'b3'], '3': 'c', '1': 'a', '4': 'd'}
    {'2': ['b1', 'b2', 'b3'], '3': 'c', '1': 'a', '4': 'd'}
    '''
    
    
    print("删除之后:")
    dict1["2"].remove("b1")
    print(dict1)
    print(dict2)
    print(dict3)
    '''
    {'2': ['b2', 'b3'], '3': 'c', '1': 'a', '4': 'd'}
    {'2': ['b2', 'b3'], '3': 'c', '1': 'a', '4': 'd'}
    {'2': ['b1', 'b2', 'b3'], '3': 'c', '1': 'a', '4': 'd'}  因为dict3是子对象也进行了拷贝,所以删除原dict1的子对象值,dict3是不变的
    '''
    
    
    
    #3、善用迭代器
    list1=[1,2,3,4,5]
    list2=[]
    
    def addlist(x):
        return x+1
    
    #多行for循环实现
    for i in range(len(list1)):
        list2.append(addlist(list1[i]))
    print(list2)
    
    
    #一行代码实现
    print(list(addlist(i) for i in list1))
    '''
    因为列表是可迭代对象,所以可以直接for循环遍历
    [2, 3, 4, 5, 6]
    [2, 3, 4, 5, 6]
    '''
    
    
    
    
    #4、慎用全局变量-莫要随意修改
    num=100
    def changeNum():
        global num
        num += 23
    changeNum()
    print("全局变num:",num)
    '''
    结果:全局变num: 123
    此时全局变量已被修改,此方式慎用,因为作为全局变量一般是可供其它函数共同使用,不可随意修改。
    '''
    
    num2=100
    def changeNum2(n):
        num2=0
        num2+=n
        num2+=23
        return num2
    num3=changeNum2(num2)
    print("全局变量num2:",num2)
    print(num3)
    '''
    结果:
    全局变量num2: 100
    123
    此种方式全局变量并未更改,应该尽量使用传参的形式来使用全局变量,而不是直接修改全局变量
    '''
    
    
    
    #5、区分 is 和 == 的区别
    # is看地址,=等号看值
    list1=[1,2,3,4,5]
    list2 = list1
    print(list2 == list1)
    print(list2 is list1)
    print(id(list1))
    print(id(list2))
    '''
    True
    True
    2152176174856
    2152176174856
    直接赋值,说明是两个对象list1和list2引用同一个内存地址
    '''
    
    list3=list1[:]
    print(list3 == list1)
    print(list3 is list1)
    print(id(list3))
    print(id(list1))
    '''
    True
    False
    2201184126728
    2201184126536
    先将list1切片再赋值给list3,中间过程是:
    list1[:]切片后已经生成了新的对象开辟了新的内存地址,
    此时赋值给list3就是新的内存地址
    '''
    
    
    
    #6、规避++和— —
    num1=3
    #num1++  SyntaxError: invalid syntax
    #num2--  SyntaxError: invalid syntax
    '''
    因为python中整型是不可变对象,而++和--就是改变其自身的值,这与python的不可变对象原则不一致,所以语法错误
    '''
    num1+=1
    num1-=1
    '''
    此种方式:先执行num1+1操作生成了新的对象开辟了新的内存地址,然后再赋值给原对象变量名num1,这样就达到了"修改"自身值的效果
    '''
    
    
    #7、作用域
    li=[lambda :x for x in range(10)]
    print(li[0]())
    print(li[2]())
    print(li[4]())
    print(li[9]())
    '''
    9
    9
    9
    9
    解释:为什么结果都是9?
    1、列表里是lambda匿名函数表达式,所以列表的每个元素都是一个函数
    2、基本知识解释:函数在定义的时候并未分配内存空间来保存变量的值,只有在执行的时候才会分配空间保存标量的值。
    3、所以该例子中没有执行print(li[0]())等时,变量x是没有值的,所以当去执行的时候才会为x赋值,但请注意:
       在执行函数是的时候,for寻循环其实早已结束,只是未给x变量赋值,所以当执行函数的时候才会为x变量赋值,此时x已经循环变成9
    4、所以最后执行的结果都是9
    
    作用域的基础知识:
    python中遇到变量寻找作用域的顺序为:
    本地作用域->外围作用域(函数体内)->全局作用域(单一文件内)->内置作用域
    def class lambda等才会产生作用域
    if for try等不会产生作用域
    '''
    #再例如:
    li2=[lambda x:x+i for i in range(3)]
    for f in li2:
        print(f(1))
    '''
    3
    3
    3
    '''
    
    #改进版:将自有参数i赋值,这样定义的i变量拥有变量值i
    li3=[lambda x,i=i:x+i for i in range(3)]
    for f in li3:
        print(f(1))
    '''
    1
    2
    3
    '''
    
    #8、列表删除
    list1=[1,5,5,5,7]
    def remove_list(n,li):
        for x in li:
            if x==n:
                li.remove(n)
        return li
    print(remove_list(5,list1))
    '''
    结果:为什么删除5未删干净?
    [1, 5, 7]
    解释:
    首先明确一点:列表元素被删除,列表是动态变化的。
    第一次循环未匹配成功,列表仍为[1,5,5,5,7]
    第二次循环索引1的值匹配成功并删除,列表变为[1,5,5,7],注意此时索引是循环到1
    第三次循环索引2的值(注意此时用的列表是[1,5,5,7]),且从索引2开始的,所以索引2的值匹配成功删除
    最后结果就变成[1,5,7]循环结束
    '''
    #改进:
    list2=[1,5,5,5,7]
    def remove_list2(n,li):
        length=len(li)
        dict1=dict(zip(range(length),li))            #将列表的每个值做一个标记形成字典{'0':'1','1':'5',...}
        return [v for k,v in dict1.items() if v!=n]  #dict1.items()为{(0,1),(1,5),...}
    print(remove_list2(5,list2))
    
    #9、字符串驻留
    x='helloword'
    y='hello'+'word'
    print(id(x)==id(y))
    #结果:True
    详见:Python内置数据类型-字符串的驻留机制
    
    #10、for循环的误区
    for i in range(4):
        print(i)
        i=5
    '''
    结果:
    0
    1
    2
    3
    i=5并不会影响循环,python中的for循环是如此工作的:range(4)生成的下一个元素被解包并赋值给目标列表变量i
    '''
    
    #11、生成器的执行时机
    nums=[4,5,6]
    g=(n for n in nums if nums.count(n)>0)
    print(list(g))
    #结果:[4, 5, 6]
    
    
    nums=[4,5,6]
    g=(n for n in nums if nums.count(n)>0)
    nums=[6,7,8]
    print(list(g))
    '''
    结果:[6]
    为什么结果不能?
    1、生成器中的in子句是在定义的时候执行
    2、生成器中的if条件子句是在运行的时候执行
    所以可以理解为:
    g=(n for n in [4,5,6] if [6,7,8].count(n)>0)
    '''
    

    相关文章

      网友评论

          本文标题:python常见错误2

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