4、迭代
我们知道可以对list,tuple,dict,str等数据类型使用for…in的循环语法,从其中依次取出数据,这个过程叫做遍历,也叫迭代。迭代是访问集合元素的一种常用的方式。
for x in [1,2,3]:
print(x)
for i in (1,2,3):
print(i)
一个对象,物理或者虚拟存储的序列。list,tuple,strins,dicttionary,set以及生成器对象都是可迭代的,整型数是不可迭代的。可迭代的对象,内部实现了__iter()__的方法。此方法也称为可迭代对象的协议。
而当内部同时实现了__iter()__和__next()__两种方法时,这个对象可以称为一个迭代器,例如我们平时操作的文件对象,就是一个迭代器。这两种方法称为迭代器的协议。
f =open('data.txt', encoding='utf-8')
# print(f.read())
# for line in f:
# print(line,end='')
print(f.__next__(),end='')
print(f.__next__(),end='')
print(f.__next__(),end='')
print(f.__next__(),end='')
迭代器和可迭代对象都能通过for循环的方法,对器内部的元素进行遍历,但两者的区别时,可迭代对象一次会把内部所有元素在内存中开辟出来,而迭代器一次只会开辟部分内存,通过内置函数__next()__或next()调用余下元素。
一个对象是否是迭代器,我们可以通过内置函数iter()来判断,当iter()的参数是一个迭代器时,他会返回迭代器对象本身,当一个对象时可迭代对象时,他会返回可迭代对象的迭代器版本。可迭代对象无法调用__next__()方法。
urls = ['youpinketang','uke.cc','codeclassroom.com']
print(iter(urls) is urls)
False
下面代码时可迭代对象的应用:
l =[1,4,9]
res =[]
s = iter(l)
while True:
try:
res.append(s.__next__()**2)
except StopIteration:
break
print(res)
上述代码可以通过列表推导来实现,列表推导通常可以作用于可得带对象或迭代器,列表推导通常也会根据外层符号返回一个可迭代对象:
>>> res =['youpinketang.com','uke.cn','codeclassroom.com']
>>> res1 = [x for x in res]
>>> res1
['youpinketang.com', 'uke.cn', 'codeclassroom.com']
>>> res2 = [x for x in res if x.endswith('.com')]
>>> res2
['youpinketang.com', 'codeclassroom.com']
另外,python内置的含有很多课生成迭代器的函数:
#zip函数会返回一个迭代器
>>> result =zip(['x','y','z'],[1,2,4])
>>> result
<zip object at 0x00000180FE066048>
>>> for x in result:
... print(x)
...
('x', 1)
('y', 2)
('z', 4)
>>> iter(result) is result
True
>>> type(result)
<class 'zip'>
#map函数也会返回一个迭代器
def double_number(x):
return x *2
l = [1,2,3,4,5]
result =list(map(double_number,l))
print(result)
t =map(double_number,l)
print(iter(t) is t)
#输出
[2, 4, 6, 8, 10]
True
另外,字典的内置方法keys(),values(),返回的视图对象,是可迭代对象。
六、函数
1、函数的定义
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
2、函数的调用
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。在函数调用处传入的参数为实参,函数定义处的参数为形参。
def read_book():
print('拿到一本书')
read_book()
def learning(name,course,start,end):#形参
print('{},{},{},{}'.format(name,course,start,end))
learning('Tom','Python入门',1,3) #实参
#输出
拿到一本书
Tom,Python入门,1,3
def add_number(x,y):
result = x+y
print(result)
return result
result = add_number(3,5)
print(result)
def multiply(x, y): return x*y # 可以放在一行
print(multiply('str',5))
#输出
8
8
strstrstrstrstr
3、变量的作用范围
变量的作用范围主要包括:
- 内置变量(Built-in),可以作用与整个程序。
- 全局变量(global)
- 封装(enclousure)
- 本地(local)
x =55 #全局变量
def func():
x = 99 #本地变量,在函数的命名空间内,与外部隔离,函数内使用x时优先就近寻找变量。
print(x)
print(x)
func()
def func():
global x #声明函数内使用的是全局变量x
x = 99
print(x)
print(x)
func()
print(x)
#输出
55
99
55
99
99
上述程序是一个典型的全局变量和局部变量的应用。
def func():
x=100 #封装,此处的x属于封装变量
def nest():
x=99
print(x)
nest()
print(x)
func()
def func():
x=100 #封装
def nest():
nonlocal x #使用的封装变量x
x=99
print(x)
nest()
print(x)
func()
#不可变类型做实参传递
def change_number(x):
x+=10
x=5
print('x={}'.format(x))
change_number(x)
print('x={}'.format(x))
#输出
x=5
x=5
def change_str(x):
s='uke.cc'
url = "youpinketang"
print(url)
change_str(url)
print(url)
#输出
youpinketang
youpinketang
#可变类型做实参传递
def change_list(x):
x[1]=233
url = ['1','2','3']
print(url)
change_list(url)
print(url)
#输出
['1', '2', '3']
['1', 233, '3']
关于参数传递的机制,连接内的文章写的很好 http://c.biancheng.net/view/2258.html,注意语函数传进去之后,都是复制了一个当前变量的副本,通过copy和[:]函数赋值的list等,相当于新开辟了一个地址存储这个列表,与源地址不一样。