变量作用域问题
总结:
- 等号赋值都会创建新对象
- 不可变变量的修改会创建新对象
- 可变对象修改就在原始地址上改
- 传参都是引用
1、赋值问题
- 不可变对象(各类容器)不可变对象+=后,地址也改了 也就是说创建了一个新的对象
- 可变对象(int那些+tuple),;且+=后,地址不变;
- 注意:如果都是用“=”重新赋值,地址都会变
- 以后写程序的时候,要注意不要让后面的值修改前面的!
2、global与local问题。。
case:
def huangwei():
name = "黄伟"
print('1',name)
def liuyang():
name = "刘洋"
print('2',name)
def nulige():
name = '沪指花'
print('3',name)
print('4',name)#先输出这个,还是刘洋
nulige()
liuyang()
print('5',name)
huangwei()
结果:
1 黄伟
2 刘洋
4 刘洋
3 沪指花
5 黄伟
- 调用全局变量 使用关键字 global
- 调用外面上一层的变量,使用关键字 nonlocal
name = "刚娘"
def weihou():
name = "陈卓"
def weiweihou():
#print('1',name) 会报错name 'name' is used prior to nonlocal declaration
nonlocal name # nonlocal,指定上一级变量,如果没有就继续往上直到找到为止
print('1',name) #还是 陈卓
name = "冷静"
weiweihou()
print('2',name) #已经修改为 冷静
print('3',name)
weihou()
print('4',name)
3 刚娘
1 陈卓
2 冷静
4 刚娘
接着第一点的赋值与传参问题
- python的赋值相当于引用,引用自身会导致死循环,values在被赋值时,就是先创建一个list对象,然后给这个对象贴上v这个标签,若v赋别的值,就是给把标签移到这个值所在对象,并没有一个叫做的v的容器在装载,而v[1]=v会让其指向自己,导致死循;
- 浅拷贝
- 1、用就可以实现[0, [0, 1, 2], 2]的结果,因为[:]操作会负责一个新对象,不会出现自己指向自己的情况
- 2、用工厂函数但是当list中出现嵌套结构时:因为a[1] b[1] 地址相同
- 3、copy函数,import copy后
- 深拷贝,拷贝了对象的所有元素,包括多层嵌套的元素。因而,它的时间和空间开销要高。对象地址同,但元素不同
- 增强赋值与共享引用,
- z=x,x = x + y:等式右边的会新建一个x对象,so最后z不改变
- z=x,x += y:z也变成x! 但比上面更高效
- 浅拷贝
- 传参问题终结者case:
def func(m): m[0] = 10 print(id(m)) #传了地址 m = [100,200,300] print(id(m)) #为m重开了地址' return m m = [1,2,3] print('元素地址:',id(m)) func(m) print('元素地址',id(m),m) print('返回新地址:',id(m),func(m)) 结果: 元素地址: 2473647109768 2473647109768 2473647108360 元素地址 2473647109768 [10, 2, 3] 2473647109768 2473647108360 返回新地址: 2473647108360 [100, 200, 300]
- 另注:解释器在对值很小的int和很短的字符串的时候做了一点小优化,只分配了一个对象,让它们id一样了,eg:
递归中的问题:
https://blog.csdn.net/anlian523/article/details/80565571
乱码问题:
- 先看要爬的页面的编码方式,https://www.cnblogs.com/Yemilice/p/6201224.html?tdsourcetag=s_pcqq_aiomsg,DS爬小说的时候,有的是GBK,有的ISO-xx
- str前面加u表示unicode编码,保证中文正常