Python基础 | 小技巧

作者: 采风JS | 来源:发表于2017-06-09 22:07 被阅读150次

    初识Python是在16年的国庆节,趁着国庆假期,弥补了些许知识。真心为其语言的简洁和美妙感动。中间陆陆续续练习过静态爬虫、简单数据处理等,收拾心情,重新整理,便于复习。

    网上以廖雪峰博客为参考资料,简单明了,方便学习。实验环境为Anaconda3,自带Python3.6。下面分享一些简单的技巧,以供参考。

    一、数据类型

    Python中内置的四种数据类型,list(列表)、tuple(元组)、dict(字典)和set(集合)。list是可变的序列,支持多种数据类型,其列表生成器、列表解析器和切片操作,是尤为关键的。tuple简单总结为不变的列表。字典与Java中的HashMap有异曲同工之妙,而集合就是没有值,只有键的字典

    1. 元组命名

    # 基于IPython环境进行交互
    from collections import namedtuple
    Student = namedtuple('Student',['stu_id','age','tel'])
    s1 =  Student('001',22,'lzw@163.com')
    # 访问学生学号有两种方式
    s1[0]与s1.stu_id
    

    2. 列表中次数统计

    # 基于IPython环境进行交互
    # 列表生成器生成随机序列
    from random import randint
    list = [randint(1,10) for x in range(1,20)] # 20次循环,产生重复数字
    # 方法一
    list_dict = dict.fromkeys(list,0) #以list为键,0为值
    for i in list:
        list_dict[i] += 1
    # 方法二
    from collections import Counter
    list_count = Counter(list)
    list_count.most_common() #以元组形式返回每个值的次数,以次数升序排列
    

    3. 以字典中值排序

    # 基于IPython环境进行交互
    # 基于字典生成器生成学生成绩,针对学生成绩进行排序
    from random import randint
    score = {x:randint(60,100) for x in ['baby','dengchao','chenhe','liche']}
    #  方法一
    sorted(list(zip(score.values(),score.keys()))) #以字典的值和键相互对应生成元组列表
    #  方法二
    sorted(score.items(),key=lambda x:x[1])
    

    4. 统计多个字典中的公共键

    # 基于IPython环境进行交互
    # 统计欧冠每轮均有进球的队员
    from random import sample,randint #sample用于产生抽样个数
    player=['c罗','梅西','本泽马','苏牙','内马尔','穆勒']
    #在队员中随机挑选三到五个人
    s1 = {x:randint(1,4) for x in sample(player,randint(3,5))}
    s2 = {x:randint(1,4) for x in sample(player,randint(3,5))}
    s3 = {x:randint(1,4) for x in sample(player,randint(3,5))}
    # 方法 map与reduce
    from functools import reduce
    reduce(lambda x,y: x&y ,list(map(dict.key,[s1,s2,s3])))
    

    二、迭代操作

    廖雪峰的博客中提到,for循环中的对象为两种类型,一种list、tuple、dict和set等可迭代对象,另一种为生成器对象。同时,还存在迭代器对象。曾经也是不能非常清晰的判别这些概念,这里姑且给出一个自己的判别准则,存在iter()方法的为可迭代对象,存在next()方法的为迭代器对象,一个对象可以同时为可迭代对象和迭代器对象。

    # 基于IPython环境进行交互
    # 进行对象类型判别
    from collections import Iterable,Iterator
    l=[x for x in range(1,10)]
    g = (x for x in range(1,10))
    ll = iter(l)
    isinstance(l,Iterable) True
    isinstance(l,Iterator) False
    isinstance(g,Iterable) True
    isinstance(g,Iterator) True
    isinstance(ll,Iterable) True
    isinstance(ll,Iterator) True
    

    1. 基于生成器的可迭代类

    # 用于产生素数的类
    class PrimeNumbers:
        def __init__(self,start,end):
            self.start=start
            self.end=end     
        def isPrime(self,k):
            if k <= 2:
                return False
            for i in range(2,k):
                if k % i == 0:
                    return False
            return True
    # 本类的关键是在__iter__函数中实现生成器,模拟next方法
        def __iter__(self):
            for k in range(self.start,self.end+1):
                if self.isPrime(k):
                    # 工作原理与next方法相同
                    yield k
    

    2. 反向迭代器

    class FloatRange:
        # 生成构造函数
        def __init__(self,start,end,step):
            self.start=start
            self.end=end
            self.step=step
        # 实现正向迭代器
        def __iter__(self):
            t = self.start
            while t <= self.end:
                yield t
                t += self.step      
        # 用于实现反向迭代器,实现__reversed__函数
        def __reversed__(self):
            t = self.end
            while t >= self.start:
                yield t
                t = t - self.step
    

    三、装饰器

    Python中的函数式编程思想,在《Java8实战》中学习过,其包括高阶函数、返回函数、匿名函数、偏函数等,装饰器以函数作为参数且返回函数,在函数运行时动态增强功能,其魔法糖功能让人应接不暇。选择两个合适的例子,一看究竟。

    1. Fibonacci数列优化装饰器

    # Fibonacci数列优化装饰器
    def memo(func):
        cache={}
        def wrap(*args):
            if args not in cache:
                cache[args]=func(*args)
            return cache[args]
        return wrap
        
    @memo
    def fibonacci(n):
        if n <= 1:
            return 1
        res = fibonacci(n-1)+fibonacci(n-2)
        return res
    # 计算fibonacci(30)需要1.68s,加上缓存装饰器后需要813ns
    # 在计算fibonacci值时,存在诸多重复的值,浪费大量的时间
    

    2. 方法元数据保存装饰器

    # 方法的元数据,包括__name__,__doc__等,被包装后自动丢失
    from functools import update_wrapper
    def mydecorator(func):
        def wrapper(*args,**kargs):
            '''wrapper function'''
            func(*args,**kargs)
        update_wrapper(wrapper,func,('__doc__','__name__'),('__dict__',))
        return wrapper    
        
    @mydecorator
    def f():
        '''f function'''
        print ('in f function')
    

    3. 检测函数参数类型

    def typeassert(*ty_args,**ty_kargs):
        def decorator(func):
            # 获取函数func的签名
            sig = signature(func)
            # 为函数的签名绑定部分参数类型
            btypes = sig.bind_partial(*ty_args,**ty_kargs).arguments
            def wrapper(*args,**kargs):
                for name,obj in sig.bind(*args,**kargs).arguments.items():
                    if name in btypes:
                        # 校验函数中的参数类型是否符合规范
                        if not isinstance(obj,btypes[name]):
                            raise TypeError("类型异常")
                return func(*args,**kargs)
            return wrapper
        return decorator
    
    @typeassert(int,str,list)
    def g(a,b,c):
        print (a,b,c)
    

    刚刚结束西安城墙13.54公里的历练,在腰酸背痛中温习了学习过的python知识,进来机器学习和深度学习席卷科研,看来得抓紧时间深入学习了,不然真的赶不上队伍了,加油吧!不知道为什么,忽然想起一句话,向死而生,尴尬了,珍惜!

    相关文章

      网友评论

        本文标题:Python基础 | 小技巧

        本文链接:https://www.haomeiwen.com/subject/ambfqxtx.html