1、Pyhton中的迭代
面试问题:python中哪些对象可以使用for循环?或者说可以遍历? 答:可d迭代的对象,或者是实现了迭代器协议的对象都是可以被循环遍历的! 在对象的内部有一个方法,__next__() 前后双下划线,可以迭代的对象、能够使用for遍历的,这个对象肯定实现了迭代协议,实现了迭代协议的特点是内部实现了__next__() 方法, 调用__next__() 方法的时候是一样一样的读取! 再全局函数中也有一个next() 方法 ,切记 他是一个全局函数!
可迭代对象和列表之间的差异:
可迭代对象在内存中只会占用一小片的内存空间! 然后读完这块空间中的数据以后,会调用__next__()方法,在所占内存空间不变的情况下,想要读取下一个就要移指针到下一个数据上! 但是列表会在内存中占用大量的存储空间,如果文件过大的话! 就会对内存造成很大的压力。
上图中第一个图是内存! 方框是迭代器的内存! ! 右图是一个列表! 如果去读取的话!就需要跟list登长的内存将数据加载进来。
迭代工具的原理:迭代工具有for 有推导 有map 。 有的类型虽然也能使用for!但是其内部并没有实现__next()__方法,是在使用for循环的时候帮他他添加的一个! 原理是这样的:
for遍历出来的迭代器分为,迭代器对象和可迭代对象:: 两者的区别是,迭代器对象已经内部实现了__next()__方法,也可以使用全局函数next(),就比如文本文件,就是一个迭代器对象,可以直接使用__next()__对象还有全局next()函数。
而可迭代对象就不一样了,可迭代对象中并没有自己实现迭代器! 需要我们手动实现,手动实现的方法就是调用 iter(想要被迭代的对象)。这样这个方法就具备了__next__ 和next()方法。就比如列表就是一个可迭代对象。
怎么样可以知道类型是否为迭代类型呢!? iter(类型1) is 类型1 。 使用一个iter方法查看。
函数的定义与参数:
函数的作用:最大化代码重用 、 最小化代码冗余 、 过程分解。
定义格式:def 函数名(参数1,参数2,.......) : 换行缩进 写方法体 ,或者写在一行也行。
调用: 函数名(实际参数)。
重点掌握:变量的作用域是(local) 外侧的变量是全局的!! 如果我们想要使用全局的变量! 需要在方法体中声明一个 global 关键字,来告诉函数,我要使用的变量是全局的变量!
其实还有一个范围!是内置范围,Built—in 这个范围,这个作用域比Global还要高! built-in这个范围就是你把python内置的函数给另外起名了!
还有一种范围:python2中没有,python3中有,叫做封装(Enclousure):使用的场景是函数套函数的时候能够使用到
例子:
def func():
x = 100
def nested():
x = 99
print(x)
nested()
print(x)
那么问题来了! 如果我想要让nested这个函数里面的x也使用func里面的函数应该怎么做呢!?
def func():
x = 100
def nested():
nonlocal x
x = 99
print(x)
nested()
print(x)
只需要加上一个nolocal这个关键字就行!
这四个的顺序是:local --->enclousure---->global----->built-in 从最低层到最高层的一个顺序。
参数的讲解:先来一个例子:
def change_number(x):
x += 10
x = 5
print('x = {}'.format(x))
change_number(x)
print('x = {}'.format(x))
输出的是:x = 5 x = 5 : 为什么这样呢?
因为,默认的情况下!我们的变量或者实际的值向我们的函数传递的时候,需要看看是什么类型!看看是否课改变的!上面的代码中传入的x =5 ,5是一个整型,是不可以被改变的!
不可改变的类型在传值的时候呢! 会先做出来一个副本出来。然后才会传递到函数中去。所以不管函数改不改变该值!都对原值没有任何影响!
如果是传递的是列表。是可以改变的类型! 那样就会改变了:
def chang_list(l):
l[1] = 99
l[2] = 20
l = [1,2,3,4,5]
print("原始的列表式是",format(l))
chang_list(l)
print("调用后的列表是",l)
这样就会改变了!如果我们不想让它进行改变的话!那么我们就在change_list(l.copy()) 在copy出来一个副本即可。这样函数无论进行什么操作,都不会影响原始值。
记住一句话:不可变类型:int型、浮点型、字符串型、tuple型、都是不可变型!都是传递副本,可变类型都是传递的地址引用!函数类操作会影响该原始值!