(XWZ)的python学习笔记Ⅰ

声明:所做笔记是基于廖雪峰老师的python教程

list,set,dict

  1. 只有list是可变对象

  2. set 中的元素是无序的,比如s = {1, 2, 3},即使现在看起来1是第一个元素,2是第二个元素,但实际上可能并非如此,因此没有s[0],s[1]这种操作。
    None和‘’、[]、{}等不一样。

  3. 只要x是非零数值、非空字符串、非空list等,就判断为True,否则为False。非零即为一

  4. for循环其实可以同时使用两个甚至多个变量,比如dict的items()可以同时迭代key和value。默认迭代的是value,当然可以用d.keys()对key进行迭代。

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> for k, v in d.items():
...     print(k, '=', v)
...
y = B
x = A
z = C

切片

  1. tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple。
  2. 字符串’xxx’也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串。
  3. l[start: end] 表示的是从start到end-1的元素。

迭代

  1. Python的for循环不仅可以用在list或tuple上,还可以作用在其他可迭代对象上。
  2. 因为dict的存储不是按照list的方式顺序排列,所以,迭代出的结果顺序很可能不一样。
  3. dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()。
  4. 字符串也是可迭代对象
  5. 通过collections模块的Iterable类型判断某个对象是否是可迭代对象。
from collections import Iterable
isinstance('abc', Iterable)
  1. 如果要对list实现类似Java那样的下标循环怎么办?Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身。
>>> for i, value in enumerate(['A', 'B', 'C']):
...     print(i, value)
...
0 A
1 B
2 C
  1. 任何可迭代对象都可以作用于for循环,包括我们自定义的数据类型,只要符合迭代条件,就可以使用for循环。

列表生成式

  1. range(start, end)生成的是从start到end-1的序列。
  2. 写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来。
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:

>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
  1. 还可以使用两层循环
>>> [x * y for x in range(1, 6) for y in range(6, 11)]
[6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 18, 21, 24, 27, 30, 24, 28, 32, 36, 40, 30, 35, 40, 45, 50]
>>> [x * y for x in range(1, 6) if x % 2 == 0 for y in range(6, 11) if y % 2 == 1]
[14, 18, 28, 36]
  1. 放在for后面的if是筛选条件,表示只选取序列中满足条件的元素。而放在前面的if是表达式,作用于x的取指,没有筛选功能。
  2. if写在for前面必须加else,否则报错
>>> [x if x % 2 == 0 for x in range(1, 11)]
 File "<stdin>", line 1
   [x if x % 2 == 0 for x in range(1, 11)]
                      ^
SyntaxError: invalid syntax

生成器

  1. generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
  2. generator也是可迭代对象,所以,我们创建了一个generator后,一般不会去调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
>>> L1 = ['Hello', 'World', 18, 'Apple', None]
>>> g = (x if x % 2 else -x for x in range(11))
>>> for x in g:
	print(x)

0
1
-2
3
-4
5
-6
7
-8
9
-10
  1. 赋值语句
a, b = b, a + b

相当于

t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
  1. 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
  2. 函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
  3. 把函数改成generator后,我们一般不会用next()来获取下一个返回值,而是直接使用for循环来迭代。但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中。
  4. 注意区分普通函数和generator函数,普通函数调用直接返回结果,generator函数的“调用”实际返回一个generator对象。

迭代器

  • 可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型,如list、tuple、dict、set、str等;

    一类是generator,包括生成器和带yield的generator function。

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

  • 可以被next()函数调用并不断返回下一个值的对象称为迭代器。

  • 生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
    把list、dict、str等Iterable变成Iterator可以使用iter()函数:

>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
  • Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

  • 凡是可作用于for循环的对象都是Iterable类型;
    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

  • range()返回的是一个可迭代对象(Iterable)

高阶函数

  • abs(-10)是函数调用,而abs是函数本身。
  • 函数本身也可以赋值给变量,即:变量可以指向函数:
>>> f = abs
>>> f(-1)
1
  • 函数名其实就是指向函数的变量!对于abs()这个函数,完全可以把函数名abs看成变量,它指向一个可以计算绝对值的函数!
    如果把abs指向其他对象,会有什么情况发生:
>>> abs = 10
>>> abs(-10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
  • 既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

map/reduce

  • 我们先看map。map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
  • reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
  • 所有的Iterator都是Iterable,反之不成立。

filter

  • 和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素
  • filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list

sorted

  • sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:
list= [1, -2, 3, -4, 5]
re = sorted(l, key = abs)

然后sorted()函数按照keys进行排序,并按照对应关系返回list相应的元素。

返回函数

  • 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
  • 我们在函数lazy_sum中又定义函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数,且他们不共用lazy_sum中的的变量。
  • 返回的函数并没有立刻执行,而是直到调用了f()才执行。
  • 另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。

你可能认为调用f1(),f2()和f3()结果应该是1,4,9,但实际结果是:

>>> f1()
9
>>> f2()
9
>>> f3()
9

全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。
返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs

装饰器

  • 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
  • 本质上,decorator就是一个返回函数的高阶函数

偏函数

  • functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单:
>>> def add(x, y):
	return x + y

>>> ad = functools.partial(add, y = 1)
>>> ad(2)
3
>>> ad(4)
5
>>> 

注意的问题

 def fun(a, b, c): 
 	return a + b + c
 f = functools.partial(fun, 1, 2)

如果用 partial 这么声明会将前两个参数固定,只需要传入第三个参数就行了。
一旦用了像ad = functools.partial(fun, b = 1)这样的形式,则在调用fun函数时,b往后的参数需要加上对应的变量名:

def fun(x, y, z):
    print('sum is', x + y + z)
ad(2, 3)	#显示错误为 TypeError: fun() got multiple values for argument 'y'
ad(2, z = 3) #运行正确

即若不指定参数名,则默认的是从左边的参数开始赋值。

额外知识点
socket.socket()绑定的是一个随机的端口,使用bind()方法可以重新绑定。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值