Python 学习笔记(高级特性)

版权声明:本文为博主原创文章,未经博主同意不可随意转载。 https://blog.csdn.net/hellokandy/article/details/85064336

【关于切片】

#例如一个列表如下:
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
print('L=', L)

#在没有使用切片之前,取列表前三项的方法可能会是:
_list = []
for i in range(3):
	_list.append(L[i])
print('_list=', _list)

#对取指定索引范围的操作,用循环十分繁琐。因此,Python提供了切片(Slice)操作符,能大大简化这种操作。
print('L[0:3]=', L[0:3])#L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3

#如果第一个索引是0,还可以省略:
print('L[:3]=', L[:3])

#Python支持L[-1]取倒数第一个元素,那么它同样支持倒数切片
print('L[-3:]=', L[-3:])
print('L[-3:-1]=', L[-3:-1])

#比如对一个1~49的奇数列表进行操作:
lst = list(range(1,50,2))#2表示步长
print('list(range(1,50,2))=', lst)
print('lst[:10]=', lst[:10])
print('lst[-10:]=', lst[-10:])
print('lst[10:20]=', lst[10:20])

#前10个数,每两个取一个:
print('lst[:10:2]=', lst[:10:2])#2表示步长

#所有数,每3个取一个:
print('lst[::3]=', lst[::3])

#甚至什么都不写,只写[:]就可以原样复制一个list:
print('lst[:]=', lst[:])


#tuple也是一种list,因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
_tuple = (1,2,3,4,5,6,7,8,9)
print('_tuple[:3]=', _tuple[:3])

#字符串'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:
print('\'ABCDEFG\'[0:3]=', 'ABCDEFG'[0:3])

#练习题目
#利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法:
def trim(x):
	n=len(x)
	idx = x.find(' ')
	if idx==-1:
		return x

	while n>0:
		if x[0]==' ':
			x=x[1:]
		elif x[-1:]==' ':
			x=x[:-1]
		n=n-1
	return x

print('trim(\'A\')=', trim('A'))
print('trim(\' ABCD  \')=', trim(' ABCD  '))

【关于迭代】

'''
在Python中,迭代是通过for ... in来完成的。而很多语言比如C语言,迭代是通过下标完成的。
Python的for循环抽象程度要高于C的for循环,因为Python的for循环不仅可以用在list或tuple上,
还可以作用在其他可迭代对象上
'''

dic = {'c++':90, 'java':88, 'python':92, 'mysql':86}
for key in dic:
	print('key in dic :', key)

#因为dict的存储不是按照list的方式顺序排列,所以,迭代出的结果顺序很可能不一样。
#默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.values()。
for value in dic.values():
	print('value in dic :', value)
	
#如果要同时迭代key和value,可以用for k, v in d.items()。
for k,v in dic.items():
	print('key:', k, ', val:', v)

#由于字符串也是可迭代对象,因此,也可以作用于for循环:
for ch in 'ABCDEFG':
	print('ch:', ch)

'''
当我们使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行。
而我们不太关心该对象究竟是list还是其他数据类型。
'''

#如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
from collections import Iterable

print('isinstance(\'abc\', Iterable):', isinstance('abc', Iterable))
print('isinstance([1,2,3], Iterable):', isinstance([1,2,3], Iterable))
print('isinstance(123, Iterable):', isinstance(123, Iterable))


#一个小问题,如果要对list实现类似Java那样的下标循环怎么办?
#Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:
for idx,value in enumerate(['AA', 'BB', 'CC']):
	print(idx, value)

#上面的for循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:
for x,y in [('apple',6.5), ('orange',7.8), ('grape',6.8), ('banana',8.4)]:
	print(x, y)


#使用迭代查找一个list中最小和最大值,并返回一个tuple:
def findMinAndMax(L):
	min=None
	max=None
	if len(L)==0:
		return (min, max)

	for n in range(0,len(L)):
		if n == 0:
			min = max = L[n]
		elif min >= L[n]:
			min = L[n]
		elif max <= L[n]:
			max = L[n]
		else:
			print('pass')
	return (min, max)

min, max = findMinAndMax([7])
print('findMinAndMax([7]): min:%d, max:%d ' % (min, max))

min, max = findMinAndMax([7,1])
print('findMinAndMax([7,1]): min:%d, max:%d ' % (min, max))

min, max = findMinAndMax([7,1,3,9,5])
print('findMinAndMax([7,1,3,9,5]): min:%d, max:%d ' % (min, max))

#改为可变参数的函数
def findMinAndMax2(*L):
	min=None
	max=None
	if len(L)==0:
		return (min, max)

	for n in range(0,len(L)):
		if n == 0:
			min = max = L[n]
		elif min >= L[n]:
			min = L[n]
		elif max <= L[n]:
			max = L[n]
		else:
			print('pass')
	return (min, max)

min, max = findMinAndMax2(7)
print('findMinAndMax2(7): min:%d, max:%d ' % (min, max))

min, max = findMinAndMax2(7,1)
print('findMinAndMax2(7,1): min:%d, max:%d ' % (min, max))

min, max = findMinAndMax2(7,1,3,9,5)
print('findMinAndMax2(7,1,3,9,5): min:%d, max:%d ' % (min, max))

【一些迭代工具】

1、并行迭代

fruits = ['apple', 'orange', 'banana', 'grape']
price = [6.5, 2.3, 3.6, 8.9]
for i in range(len(fruits)):
	print(fruits[i], 'is', price[i], 'yuan per kilogram')

#使用内建函数zip进行改造
zip(fruits, price)
print(zip(fruits, price))

#内建函数zip可以用来进行并行迭代,把两个序列"压缩"在一起,然后返回一个元组的列表
for name, price in zip(fruits, price):
	print('zip mode:', name, 'is', price, 'yuan per kilogram')

2、按索引迭代

strings = 'hello,thisiskandy'
for szSub in strings:
	if 't' in szSub:
		index = strings.index(szSub)
		print('index:', index)

3、翻转和排序迭代

lst = sorted([1,5,4,3,2,6])
print('sorted([1,2,3,4,5,6])=', lst)

str = ''.join(reversed('hello,world!'))
print('str reverse : ', str)
#注意:reversed返回的是一个可迭代的对象

【列表推导式】

#也叫列表生成式,是利用其它列表创建新的列表
#写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来
lst = [x*x for x in range(10)]
print('lst:', lst)
#[0,1,4,9,16,25,36,49,64,81]

#只打印被3整除的平方数
lst2 = [x*x for x in range(10) if x%3 == 0]
print('lst2:', lst2)
#[0,9,36,81]

#还可以使用两层循环,可以生成全排列:
lst3 = [m + n for m in 'ABC' for n in 'XYZ']
print('lst3:', lst3)

#打印指定路径下的目录与文件
import os
#path = 'C:/Users/Public'
path = r'C:\Users\Public'
dirs = [d for d in os.listdir(path)]# os.listdir可以列出文件和目录
for filename in dirs:
	print('filename:', filename)

#把list中所有字符串变成小写:
rawlst = ['Apple', 'Banana', 'Grape', 'Orange']
lowlst = [s.lower() for s in rawlst]
print('rawlst:', rawlst)
print('lowlst:', lowlst)

#将list(既有字符串也有数字)中包含的字符串转小写后输出
L1 = ['Apple', 'Banana', 'Grape', 'Orange', 12, 45]

#使用内建的isinstance函数可以判断一个变量是不是字符串
L2 = [s.lower() for s in L1 if isinstance(s, str)]
print('L2:', L2)

【关于生成器】

#回顾一下列表生成式的写法:
L = [x * x for x in range(10)]
print('L=', L);

'''
通过列表生成式,我们可以直接创建一个列表。
但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,需要占用很大的存储空间。
如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
'''

#要创建一个generator,有很多种方法。
#第一种方法:只要把一个列表生成式的[]改成(),就创建了一个generator:
g = (x * x for x in range(10))
print('g=', g)

#如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
print('next(g)=', next(g))#输出0
print('next(g)=', next(g))#输出1
print('next(g)=', next(g))#输出4
#generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,
#直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

#纵使next(g)可以取到数据,但正确的方法是使用for循环(并且无需关心StopIteration的错误),因为generator也是可迭代对象:
for n in g:
	print('n in g = ', n)
#输出:9,16,25,36,49,64,81。可以看出:它是从上次访问的位置继续往下输出。


#第二种方法:使用yield关键字
'''
在Python中,使用了yield的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
'''

#比如,著名的斐波拉契数列(Fibonacci)
def fib(max):
	n,a,b = 0,0,1
	while n < max:
		print(b)
		a, b = b, a+b
		n = n + 1
	return 'done'

#测试
print(fib(6))


#使用yield实现斐波那契数列:
def fibonacci(max):
	n,a,b = 0,0,1
	while n < max:
		yield(b) #每次运行至此暂停,并保存当前所有运行信息,返回yield的值
		a, b = b, a+b
		n = n + 1
	return 'done'

f = fibonacci(6) # f是一个迭代器,由生成器返回生成
print('fibonacci(6):', f)

#打印斐波那契数列的元素
import sys
while True:
    try:
        print(next(f), end=",")
    except StopIteration:
        print('StopIteration')
        break
        #sys.exit()

#用for循环调用generator时,发现拿不到generator的return语句的返回值。
#如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
f = fibonacci(7)
while True:
	try:
		print(next(f), end=" ")
	except StopIteration as e:
		print('Generator return value:', e.value)
		break

猜你喜欢

转载自blog.csdn.net/hellokandy/article/details/85064336