初识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知识,进来机器学习和深度学习席卷科研,看来得抓紧时间深入学习了,不然真的赶不上队伍了,加油吧!不知道为什么,忽然想起一句话,向死而生,尴尬了,珍惜!
网友评论