zoukankan      html  css  js  c++  java
  • 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-99
    L[:10] #前10
    L[-10:] #后10
    L[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 Iterable
    isinstance('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('.')]
    
    #两个变量生成list
    d={'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))  #()而非[]
    g
    next(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对象,以下都为True
    from collections import Iterable
    isinstance([],Iterable)
    isinstance({},Iterable)
    isinstance('abc',Iterable)
    isinstance((x for x in range(10)),Iterable)
    

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

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

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

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

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

    函数式编程

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

    1.高阶函数

    变量可以指向函数

    x=abs(-10) #赋值
    x
    
    f=abs  #赋函数
    f
    f(-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*x
    
    r=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 reduce
    digits={'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 reduce
    digits={'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 == 1
    
    list(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 sum
    
    f=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 fs
    
    f1, 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 * x
    f
    f(5)
    
    #作为返回值
    def build(x, y):
        return lambda: x * x + y * y
    

    4.装饰器

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

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

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

    now.__name__  #now
    f.__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 functools
    
    def log(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('call %s():' % func.__name__)
            return func(*args, **kw)
        return wrapper
        
    #带参数的装饰器:
    import functools
    
    def 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 functools
    int2 = functools.partial(int, base=2) #实际上固定了int()函数的关键字参数base
    int2('10010')
    int2('10010', base=10)
    
    max2 = functools.partial(max, 10) #10会作为*args的一部分自动加到左边
    max2(5, 6, 7) #相当于max2(10,5, 6, 7)
    
  • 相关阅读:
    TCP校验和
    Python8 数据库基础
    Python7 TCPIP协议与抓包
    Python6 线程与进程、网络编程、生成器与迭代器、协程、异步IO
    python2 变量与数据类型
    Python10 前端基础与爬虫
    Python11 Scrapy框架基础
    python3 函数、运算符与数据类型的常用方法
    Python9 数据库进阶
    python1 简介
  • 原文地址:https://www.cnblogs.com/jessepeng/p/11221878.html
Copyright © 2011-2022 走看看