《Python 进阶》复盘笔记 - 小技巧

1, * 分割字符串

_list = ['name', 'age', '2020', '10', '10']

name, age, *years = _list
print(name)
print(age)
print(years)

# output:
# name
# age
# ['2020', '10', '10']

2, *,** 函数传参

args = ['csdn', 100, 'https://www.youkuaiyun.com/']
kwargs = {
    'name': 'csdn',
    'age': 100,
    'url': 'https://www.youkuaiyun.com/'
}


def print_info(name, age, url):
    print(name)
    print(age)
    print(url)


print_info(*args)
print_info(**kwargs)

# output:
# csdn
# 100
# https://www.youkuaiyun.com/ 
# csdn
# 100
# https://www.youkuaiyun.com/ 

3, Filter 列表过滤

  • 过滤None值
_list = [0, 1, None, 'None', {}, [], '']

new_list = filter(lambda x: x, _list)
print(list(new_list))

# output:
# [1, 'None']
  • 过滤不符合条件的值
_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

new_list = filter(lambda x: x > 6, _list)
print(list(new_list))

# output:
# [7, 8, 9]

4, Reduce 列表计算

  • 实现列表每个元素相加/乘
from functools import reduce

_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(reduce(lambda x, y: x + y, _list))
print(reduce(lambda x, y: x * y, _list))

# output:
# 45
# 362880

5, 列表推导式

列表推导式也可以完成 filter 的功能

_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

new_list = [i for i in _list if i > 6]
print(new_list)

# output:
# [7, 8, 9]

filter 和列表推导式性能对比:

import time
from functools import reduce

_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
filter_l = []
times = 1000000

for i in range(times):
    start = time.time()
    new_list = filter(lambda x: x > 6, _list)
    end = time.time()
    filter_l.append(end - start)
print(reduce(lambda x, y: x + y, filter_l) / times)

# output:
# 2.3841428756713868e-07

import time
from functools import reduce

_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
comprehensions_l = []
times = 1000000

for i in range(times):
    start = time.time()
    new_list = filter(lambda x: x > 6, _list)
    end = time.time()
    comprehensions_l.append(end - start)
print(reduce(lambda x, y: x + y, comprehensions_l) / times)

# output:
# 2.3479533195495605e-07

两种方法过滤列表性能差不多,但是列表推导式语法更为简洁。

6, slots 魔法

一般来说,类使用一个字典保存实例的属性。

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


class B(object):
    __slots__ = ['name', 'age']

    def __init__(self, name, age):
        self.name = name
        self.age = age


a = A(name='a', age='100')

print(dir(A))
print(dir(B))
print(a.__dict__)

# output:
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
# ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'age', 'name']
# {'name': 'a', 'age': '100'}

从输出上,可以明显看出 class B 少了一个 __dict__ 属性,这是由于 B 定义了 __slots__,告诉 Python 不要生成 __dict__, 从而减少了内存的使用。

7, defaultdict 为字典保留多个值

from collections import defaultdict

colours = (
    ('Yasoob', 'Yellow'),
    ('Ali', 'Blue'),
    ('Arham', 'Green'),
    ('Ali', 'Black'),
    ('Yasoob', 'Red'),
    ('Ahmed', 'Silver'),
)

favourite_colours_l = defaultdict(list)
favourite_colours_s = defaultdict(str)

for name, colour in colours:
    favourite_colours_l[name].append(colour)
    favourite_colours_s[name] += colour + ' '

print(dict(favourite_colours_l))
print(dict(favourite_colours_s))

# Output:
# {'Yasoob': ['Yellow', 'Red'], 'Ali': ['Blue', 'Black'], 'Arham': ['Green'], 'Ahmed': ['Silver']}
# {'Yasoob': 'Yellow Red ', 'Ali': 'Blue Black ', 'Arham': 'Green ', 'Ahmed': 'Silver '}

8, defaultdict 为字典嵌套赋值

import collections
import json

tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"
print(json.loads(json.dumps(some_dict)))

# Output:
# {'colours': {'favourite': 'yellow'}}

9, enumerate 遍历计数

my_list = ['apple', 'banana', 'grapes', 'pear']
for c, value in enumerate(my_list, 1):
    print(c, value)

# Output:
# (1, 'apple')
# (2, 'banana')
# (3, 'grapes')
# (4, 'pear')

10, dir 列举对象的所有属性和方法

from collections import defaultdict

favourite_colours = defaultdict(str)

print(dir(favourite_colours))

# Output:
# ['__class__', '__contains__', '__copy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__missing__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'default_factory', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

11, else 从句

  • try else 从句会在没有抛出错误时执行
try:
    print('I am sure no exception is going to occur!')
except Exception:
    print('exception')
else:
    # 这里的代码只会在try语句里没有触发异常时运行,
    # 但是这里的异常将不会被捕获
    print('This would only run if no exception occurs. And an error here '
          'would NOT be caught.')
finally:
    print('This would be printed in every case.')

# Output: I am sure no exception is going to occur!
# This would only run if no exception occurs.
# This would be printed in every case.
  • for else 从句会在循环正常结束时执行
max_ = 100
for i in range(100):
    if i > max_:
        raise Exception(f'i > {max_}')
else:
    print('not raise any error')

# Output:
# not raise any error

12, 协程

Python中的协程和生成器很相似但又稍有不同。主要区别在于: 生成器是数据的生产者 协程则是数据的消费者

  • 生成器

def range_(num):
    for i in range(num):
        yield i


for i in range_(10):
    print(i)

# Output:
# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
  • 协程, python 实现 grep

def search(key):
    while True:
        line = (yield)
        print(line if key in line else 'No')


s = search('python')
next(s)  # 启动协程
s.send('hello world')
s.send('hello java')
s.send('hello python')
s.send('hello php')
s.close()  # 关闭协程
s.send('close?')

# Output:
# No
# No
# hello python
# No
# Traceback (most recent call last):
#   File "/home/kaige/Github/gov/cn12348/tools/test.py", line 14, in <module>
#     s.send('close?')
# StopIteration

13, 函数缓存

当一个I/O密集的函数被频繁使用相同的参数调用的时候,函数缓存可以节约时间。

import time
from functools import lru_cache


@lru_cache(maxsize=32)
def func(n):
    return n ** 10


def func_nocache(n):
    return n ** 10


start = time.time()
[func(10) for _ in range(1000000)]
end = time.time()
print(end - start)

start = time.time()
[func_nocache(10) for _ in range(1000000)]
end = time.time()
print(end - start)

# Output:
# 0.06982040405273438
# 0.23273038864135742

经过测试,使用函数缓存,在使用相同参数调用同一函数时,至少能提高4倍效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值