Spensor

导航

Python学习记录

从这学期(2018.3)开始了学习python,由于以前太怠惰底子不好,学习比较慢,于是决定记录下来这个过程-0-

刚入门是跟着廖雪峰的python教程写的!个人觉得很不错!

 

python的高级特性-切片:

我们会经常取一个list或tuple中的部分元素出来,如果每次取少量元素,可以直接使用索引取出,若是取出n(n非常大)个元素时,明显这样做是不理智的。因此,Python提供了切片操作符。

L[a:b]则表示取出L中从L[a]开始到L[b-1]的所有元素,例:

L=['doris','spensor','aria','alison"]

L[0:3]=L[:3]=L[0:]=['doris','spensor','aria']

L[1:3]=['spensor','aria']

也可以使用复数,表示倒序切片

L[-2:]=['aria','alison"]

练习

利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法:

def trim(s):

  while(s[:1]==' '):
    s=s[1:]
  while(s[-1:]==' '):
    s=s[:-1]
  if(s):
    return s
  else:
    return ''

 

 

列表生成式:

列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。

举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11))

一些例子:

s=[x*x for x in range(1,11) if x*2==0]

print(s)----->[4,16,36,64,100]

还可以使用两层循环,可以生成全排列:

>>>[m+n for m in 'ABC' for n in 'XYZ']

['AX','AY','AZ','BX','BY','BZ','CX','CY','CZ']

同时使用多个变量:

>>>d={'x':'A','y':'B','z':'C'} #d是一个dict

>>>for k,v in d.items():

            print(k,'=',v)

y=B

x=A

z=C                                 #dict内部存放的顺序和key放入的顺序是没有关系的

 

 

 

生成器(重点):

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

创建generator:

>>>g=(x*x for x in range(10))

>>>g

<generator object<genexpr> at 0x1022ef630>

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值。

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

定义generator的另一种方法:

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

例:

def odd():

  print("step1')

  yield 1

  print("step2')

  yield 3

  print("step3')

  yield 5

>>>0=0dd()

>>>next(o)

step1

1

>>>next(o)

step2

3

>>>next(o)

step3

5

>>>next(o)

Traceback (more recent call last):

  File"<stdin>",line 1,in <module>

StopIteration   #执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就报错。

练习:

杨辉三角定义如下:

          1
         / \
        1   1
       / \ / \
      1   2   1
     / \ / \ / \
    1   3   3   1
   / \ / \ / \ / \
  1   4   6   4   1
 / \ / \ / \ / \ / \
1   5   10  10  5   1

把每一行看做一个list,试写一个generator,不断输出下一行的list:

# 期待输出:
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]
# [1, 5, 10, 10, 5, 1]
# [1, 6, 15, 20, 15, 6, 1]
# [1, 7, 21, 35, 35, 21, 7, 1]
# [1, 8, 28, 56, 70, 56, 28, 8, 1]
# [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
测试程序n = 0results = []
for t in triangles():
    print(t)
    results.append(t)
    n = n + 1
    if n == 10:
        break
if results == [
    [1],
    [1, 1],
    [1, 2, 1],
    [1, 3, 3, 1],
    [1, 4, 6, 4, 1],
    [1, 5, 10, 10, 5, 1],
    [1, 6, 15, 20, 15, 6, 1],
    [1, 7, 21, 35, 35, 21, 7, 1],
    [1, 8, 28, 56, 70, 56, 28, 8, 1],
    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
]:
    print('测试通过!')
else:
    print('测试失败!')

编写generator:
def triangles():
  L = [1]
  while True:
    yield L
    L.append(0)
    L = [L[i - 1] + L[i] for i in range(len(L))]
解析
杨辉三角每一行的每个元素是由前一行的相邻元素相加得到,而每行的首位又保持为1,

核心思路在于L.append(0)这一行代码,也就是每次都在list末尾添加一个0,
用于让每行的首尾等于1并让列表生成式的计数器+1(len())

这样,L = [L[i - 1] + L[i] for i in range(len(L))]
得到的第一个元素是原数组的倒数第一个元素(即0)加上第一个元素(1)等于1,#L[-1]表示倒数第一个元素
最后一个元素是原数组的倒数第二个元素(即1)加上倒数第一个元素(0)等于1,满足了条件。
这里补零和-1取倒数的思想非常重要!
但是!!!
我们会发现,测试不通过,因为每一行(除了最后一行)后面都多了一个0
你或许会疑问,0不是在yield之后再加上去的吗,为什么会显示出来呢?
这里就需要提到python中的赋值,其实都是对象的引用,L总是指向那片内存,
L.append(0) 执行后,L指向的地址的内容发生了变化
这里如果我们使用拷贝,则可测试通过
def triangles():
  L = [1]
  while True:
    yield L
    temp = L.copy()
    temp.append(0)
    L = [temp[i-1]+temp[i] for i in range(len(temp))]
注意理解!
(-------------------------18.3.30---------------------------)

posted on 2018-03-31 01:52  Spensor  阅读(105)  评论(0)    收藏  举报