13、Pythonic

作者: IT_Freak | 来源:发表于2018-12-25 16:01 被阅读0次

    Pythonic:极具Python特色的Python代码(明显区别于其它语言的写法的代码)

    用字典映射代替switch case语句

    if/else可以代替switch但是非常不合适。

    用字典代替switch:
    day = 5
    switcher = {
        0:'Sunday',
        1:'Monday',
        2:'Tuesday'
    }
    
    day_name = switcher.get(day,'Unknow')  #第一个参数为key,第二个参数为key不存在返回的值
    
    
    用字典模拟带函数的switch:
    day = 6
    def get_sunday():
        return 'Sunday'
    
    def get_monday():
        return 'Monday'
    
    def get_tuesday():
        return 'Tuesday'
    
    def get_default():
        return 'Unknow'
    
    switcher = {
        0:get_sunday,
        1:get_monday,
        2:get_tuesday
    }
    
    day_name = switcher.get(day,get_default)()
    print(day_name)
    

    列表推导式

    根据已经存在的列表创建新的列表:

    a = [1,2,3,4,5,6,7,8]
    b = [i * i for i in a]
    
    print(b)
    结果:[1, 4, 9, 16, 25, 36, 49, 64]
    
    条件筛选:
    a = [1,2,3,4,5,6,7,8]
    b = [i**2 for i in a if i >= 5]
    
    print(b)
    结果:[25, 36, 49, 64]
    
    a是集合、字典、元组也可以被推导。
    

    字典编写列表推导式

    students = {
        'tai':18,
        'park':32,
        'a':12
    }
    
    b = [key for key,value in students.items()]
    print(b)
    结果:['tai', 'park', 'a']
     
    b = {value:key for key,value in students.items()}
    print(b)
    结果:{18: 'tai', 32: 'park', 12: 'a'}
    

    迭代器(iterator)

    可迭代对象(iterable):可被for in循环遍历的对象

    普通对象变成迭代器需要实现__iter__()和__next__():
    class BookCollection:
        def __init__(self):
            self.data = ['《往事》','《只能》','《回味》']
            self.cur = 0
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.cur >= len(self.data):
                raise StopIteration()
            r = self.data[self.cur]
            self.cur += 1
            return r
    
    books = BookCollection()
    for book in books:
        print(book)
    
    除了for in 遍历,还可以调用next方法:
    
    books = BookCollection()
    print(next(books))
    print(next(books))
    print(next(books))
    
    迭代器具有一次性,只能遍历一次。若想再次遍历需要实例化一个新的对象。或者:
    import copy
    books = BookCollection()
    books_copy = copy.copy(books)    #浅拷贝
    若想实现深拷贝的话:
    books_copy = copy.deepcopy(books)    #生成器
    

    生成器(generator)

    打印从0-10000的数字:
    n = [i for i in range(0,10001)]
    for i in n :
        print(i)
    
    可以实现但是太消耗内存。n是一个列表,列表存储需要消耗内存的。
    
    
    生成器:迭代器是针对一个对象的,生成器是针对一个函数的。
    函数实现法:
    def gen(max):
        n = 0
        while n <= max:
            print(n)
            n += 1
    
    gen(100000)
    
    每次打印的都是实时计算出来的结果,不是都存储起来再打印。
    不应该在函数内部实现如print这样的操作。
    
    生成器:
    def gen(max):
        n = 0
        while n <= max:
            n += 1
            yield n
    
    g = gen(10)
    for i in g:
        print(i)
    yield会接着返回的地方继续执行。
    
    n = (i for i in range(0,10001))
    此时n也为生成器。
    

    None

    • None 空,不等于空字符串、空列表、0、False
    • None不仅在类型上不同,而且在值的比较上也不相同。
    • None永远对应False
    a = None
    print(not a)
    print(a is None) 
    结果:True
          True
    
    a = []
    print(not a)
    print(a is None) 
    结果:True
          False
     
    推荐if a/if not a来判空。
    

    对象存在并不一定是True

    自定义的对象:
    class Test():
        def __len__(self):
            return 0
    
    test = Test()
    if test:
        print('s')
    else:
        print('f')
    结果:f    #进的是False分支
    
    test存在也有可能是False,需要考虑__len__与__bool__方法。
    

    lenbool内置方法

    如果对象没有定义__len__与__bool__方法则默认为True。
    
    __len__代表长度,只能用int和bool返回。
    使用len()时,则会调用对象的__len__,如果没有自定义__len__,求长度的时候会报错。
    
    一旦加入了__bool__则由__bool__来控制对象的取值。
    

    装饰器的副作用

    import time
    
    def decorator(func):
        def wrapper():
            print(time.time())
            func()
        return wrapper
    
    
    def f1():
         print(f1.__name__)
    
    f1()
    结果:f1            #不加装饰器的函数名字
    
    @decorator
    def f1():
        print(f1.__name__)
    
    f1()
    结果:1532492964.0116718
          wrapper    #闭包函数的名字
    
    
    python->help(len)->打印出内置说明
    加了装饰器之后就无法找到函数的help()了
    
     
    保证名字不改变:
    import time
    
    from functools import wraps
    def decorator(func):
        @wraps(func)
        def wrapper():
            print(time.time())
            func()
        return wrapper
    
    @decorator
    def f1():
        print(f1.__name__)
    
    f1()
    结果:1532493245.2623913
         f1
    
    wraps传入了原有函数,所以得知了原函数的信息,然后复制到闭包函数上,则信息得以保存。
    

    相关文章

      网友评论

        本文标题:13、Pythonic

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