Python基础笔记3(python 菜鸟教程3)

网友投稿 311 2022-08-31


Python基础笔记3(python 菜鸟教程3)

高级特性

代码不是越多越好,而是越少越好。代码不是越复杂越好,而是越简单越好。代码越少,开发效率越高。

1.切片

切片(Slice)操作符,取一个list或tuple的部分元素非常常见。列表

L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']L[0:3]L[1:3]L[-1]L[-2:]L=list(range(100) #0-99L[:10] #前10L[-10:] #后10L[10:20]L[:10:2] #前10,每两个取一个L[::5] #所有数中每5个取一个

tuple

(0,1,2,3,4,5)[:3]  #得到的也是一个tuple(0,1,2)

字符串

'ABCDEFG'[:3]  #ABC'ABCDEFG'[::2] #ACEG

不像R和Perl等专门提供字符串截取函数,Python中用一个切片操作就可完成,灵活使用能减少不少循环。

2.迭代iteration

通过for循环来遍历

d={'a':1, 'b':2, 'c':3}for key in d: #字典默认迭代key     print(key) #无序#迭代值for value in d.values():  #括号不可少    print(value)#迭代键和值for k,v in d.items():

判断一个对象是否可迭代

from collections import Iterableisinstance('abc',Iterable) #字符串可迭代isinstance([1,2,3],Iterable) #list可迭代isinstance(123,Iterable) #整数不可迭代

实现下标(元素索引)迭代循环

for i, value in enumerate(['a','b','c']):    print(i, value)

同时对多个变量循环

for x,y,z in [(1,2,3),(2,3,1),(2,1,3)]:    print(x,y,z)

任何可迭代对象都可以作用于for循环,包括我们自定义的数据类型,只要符合迭代条件,就可以使用for循环。

3.列表生成式

list(range(1,11))  #1..10[x*x for x in range(1,11)][x*x for x in range(1,11) if x % 2 ==0][m+n for m in 'abc' for n in 'xyz']

应用

#列出当前目录所有文件和目录名import os[d for d in os.listdir('.')]#两个变量生成listd={'x':1, 'y':2, 'z':3}[k + '=' +v  for k,v in d.items()]#所有list字符串小写    L=["aBC","Word"][s.lower() for s in L if isinstance(s,str)==True] #列表中只能都为str

4.生成器generator

一边循环一边计算。 创建生成器:

g=(x*x for x in range(10))  #()而非[]gnext(g)next(g)...... #一个个打印出来,直到最后一个元素for n in g: #可迭代    print(n)

用一个函数来实现generator。普通函数调用直接返回结果,生成器函数调用返回的是一个生成器对象。

#斐波那契数列def fib(max):    n,a,b = 0,0,1    while n < max:        yield b  #yield关键字        a,b = b,a+b        n = n+1    return 'done'    for n in fib(6):    print(n)  #不会返回return的值    #return的值包含在StopIteration错误的value中:g=fib(6)while True:    try:        x=next(g)        print('g:',x)    except StopIteration as e:        print('Generator return value:', e.value)        break

练习:写一个generator,不断输出杨辉三角的下一行

# _*_ coding: utf-8 _*_def triangles():    L=[1]    yield L    while True:        #两端都是1,中间是上两个相邻数之和        L=[1]+[L[x]+L[x+1] for x in range(len(L)-1)]+[1]        yield L

5.迭代器

可迭代对象(Iterable):可直接作用于for循环的对象,一类是集合数据类型(list/tuple/dict/set/str),一类是generator(生成器和带yield的生成器函数)

#判断对象是否为Iterable对象,以下都为Truefrom collections import Iterableisinstance([],Iterable)isinstance({},Iterable)isinstance('abc',Iterable)isinstance((x for x in range(10)),Iterable)

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

from collections import Iteratorisinstance([],Iterator) #Falseisinstance({},Iterator) #Falseisinstance('abc',Iterator) #Falseisinstance((x for x in range(10)),Iterator) #True

生成器都是迭代器对象,list/dict/str虽然是可迭代对象,但不是迭代器。但它们可用iter()函数变成迭代器。

isinstance(iter([]),Iterator) #Trueisinstance(iter('abc'),Iterator) #True

迭代器对象是一个数据流,它是惰性的,只能通过next函数按需计算下一步。

函数式编程

函数式编程是一种抽象程度很高的编程范式,纯函数式编程甚至没有变量(python不是)。其特点是允许把函数本身作为参数传入另一个函数,还允许返回一个函数。

1.高阶函数

变量可以指向函数

x=abs(-10) #赋值xf=abs  #赋函数ff(-10)

传入函数参数

def add(x,y,f):    return f(x)+f(y)add(-5,6,abs)

map/reduce map(function,Iterable)

def f(x):    return x*xr=map(f,[1,2,3,4])list(r)#简写list([map(str,[1,2,3,4]))

reduce(f,[x1,x2,x3]) = f(f(x1,x2),x3)

from functools import reduce    def add(x,y):        return x+y        reduce(add,[1,3,5,7,9])

map和reduce结合使用:

#字符串转化为整数函数from functools import reducedigits={'0':0,'1':1,'2':2,'3':3}def str2int(s):    def fn(x,y):        return x*10+y    def char2num(s):        return digits[s]    return reduce(fn, map(char2num,s))    str2int('123')

以上函数还可进一步用lambda函数简化:

from functools import reducedigits={'0':0,'1':1,'2':2,'3':3}def char2num(s):    return digits[s]def str2int(s):    return reduce(lambda x,y: x*10+y, map(char2num,s))

filter 过滤序列,从一个序列中筛出符合条件的元素

def is_odd(n):    return n % 2 == 1list(filter(is_odd,[1,2,3,4,5])) #1,3,5

用filter筛选全体质数(素数):

#先构造一个从3开始的奇数序列def _odd_iter():    n=1    while True:        n=n+2        yield n#然后定义一个筛选函数def _not_divisible(n):    return lambda x: x%n > 0#最后定义一个生成器,不断返回下个素数def primes():    yield 2    it = _odd_iter() #初始序列    while True:        n=next(it) #返回第一个数        yield n        it = filter(_not_divisible(n),it) #构造新序列        #打印1000内的素数for n in primes():    if n < 1000:        print(n)    else:        break

筛选回数:

def is_palindrome(n):    return str(n)==str(n)[::-1]output = filter(is_palindrome, range(1, 1000))print('1~1000:', list(output))

sorted 排序算法

sorted([3,5,-23,4,-8])sorted([3,5,-23,4,-8], key=abs) #按绝对值排序sorted(['bob', 'about', 'Zoo', 'Credit']) #默认ASCII码['Credit', 'Zoo', 'about', 'bob']sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) #['about', 'bob', 'Credit', 'Zoo']sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True) #反向 ['Zoo', 'Credit', 'bob', 'about']

用sorted()排序的关键在于实现一个映射函数。

2.返回函数

把函数作为结果值返回

def lazy_sum(*args):    def sum():        ax=0        for n in args:            ax=ax+n        return ax    return sumf=lazy_sum(1,2,5,7)f #返回的是函数f() #返回结果#每次调用都会返回一个新的函数,即使参数相同也不一样f1=lazy_sum(1,2,5,7)f2=lazy_sum(1,2,5,7)f1==f2  #False,f1()和f2()的调用结果互不影响。

闭包 上例中,在函数lazy_sum中又定义了函数sum,并且内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种程序结构称为“闭包(Closure)”。

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

def count():    fs = []    for i in range(1, 4):        def f():             return i*i        fs.append(f)    return fsf1, f2, f3 = count()#f1()f2()f3()都是9,因为返回的函数引用了变量i,但它并非立刻执行,等到3个函数都返回时,它们所引用的变量i已经变成了3。

如果一定要引用循环变量,就再创建一个函数,用该函数的参数绑定循环变量当前的值:

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

3.匿名函数

关键字lambda表示匿名函数

list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))#赋值变量f = lambda x: x * xff(5)#作为返回值def build(x, y):    return lambda: x * x + y * y

4.装饰器

函数也是对象,可赋值给变量,并调用。

def now():    print('2019-1-1')f=nowf()

函数对象的__name__属性可得到函数的名字:

now.__name__  #nowf.__name__  #now

想增加函数的功能,又不想修改函数的定义,这种在代码运行期间动态增加功能的方式称为“装饰器(Decorator)”。

本质上装饰器就是一个返回函数的高阶函数。

#定义一个能打印日志的装饰器:函数作为参数并返回函数def log(func):    def wrapper(*args, **kw):        print('call %s():' % func.__name__)        return func(*args, **kw)    return wrapper@log  #把装饰器置于函数的定义处,相当于now = log(now)def now():    print('2019-1-1')    now() #调用函数,会打印日志

如果要自定义log文本,需要编写一个返回装饰器的高阶函数:

def log(text):    def decorator(func):        def wrapper(*args, **kw):            print('%s %s():' % (text, func.__name__))            return func(*args, **kw)        return wrapper    return decorator    #三层嵌套的装饰器调用:@log('execute')  #相当于now = log('execute')(now)def now():    print('2015-3-25')

完整的装饰器写法:

import functoolsdef log(func):    @functools.wraps(func)    def wrapper(*args, **kw):        print('call %s():' % func.__name__)        return func(*args, **kw)    return wrapper    #带参数的装饰器:import functoolsdef log(text):    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kw):            print('%s %s():' % (text, func.__name__))            return func(*args, **kw)        return wrapper    return decorator

面向对象的装饰模式需要通过继承和组合来实现,Python的decorator可以用函数实现,也可以用类实现。

5.偏函数

functools模块提供的偏函数:当函数的参数个数太多化时,可创建一个新的函数,将某些参数给固定住(即设置默认值),从而在调用时更简单。

#自定义函数def int2(x,base=2): #默认转化二进制    return int(x,base)#使用偏函数import functoolsint2 = functools.partial(int, base=2) #实际上固定了int()函数的关键字参数baseint2('10010')int2('10010', base=10)max2 = functools.partial(max, 10) #10会作为*args的一部分自动加到左边max2(5, 6, 7) #相当于max2(10,5, 6, 7)

作者:Bioinfarmer


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Python基础笔记2(python1%2)
下一篇:Java中lambda表达式的基本运用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~