函数
为什们要使用函数?
1.代码重用,提高效率
2.模块独立,方便扩展、修改
1.定义一个函数格式
def 函数名 (参数列表):
函数体
2.函数的命名规则
和变量一样,函数名由字母、数字、下划线组成,必须以字母或者下划线开头,且不能是保留字。
#定义一个最简单的无参数函数
def hello():
print("Hello world")
#函数hello()的调用:
hello()
>>>
Hello world
#定义一个计算从1到num累加和的函数caculate_num()
def caculate_num(num):
res=0;
for i in range(num+1):
res+=i
return res
#调用函数caculate_num() 求1~100的累加和:
print(caculate_num(100))
>>>
5050
3.形参和实参
形式参数——是虚拟变量,目的是在调用函数时接受实参
在python中,函数的形式参数无需指明类型
实际参数——调用时传给函数的参数
区别:形参是虚拟的不占据内存,只有在被调用的时候才分配内存单元;形参是一个变量,占用内存空间,数据单向由实参传递给形参
#定义一个求面积的函数
def area(weight,height):
return weight*height
#调用
w=4
h=5
print(area(w,h))
>>>
20
其中w和h是实际参数,weight和height是实际参数
4.函数文件相互调用
在一个项目中,往往每个人负责一部分功能,写成相应的函数. py文件,然后在main函数中用import
命令可以实现文件中相关函数的互相调用 (类似于c++中的 #include<头文件>
命令)
-
步骤1.在新建的python file中定义要实现相关功能的函数
-
步骤2.将文件重命名能体现其功能的样式
右击demo12文件,选择Refactor——>Rename
我们将这个包命名成cacul (命名不要和python库中已有的包重名)
然后点击 refactor ———>Do Refactor 完成重命名
-
步骤3.在另一个python file中调用这个文件
在这个工程下新建一个测试文件test.py 用import命令调用相关函数
import cacul #在测试文件中导入求和功能的文件
ans=cacul.caculate_num(100) # 调用cacul包中的caculate_num()函数
print(ans)
>>>
5050
代码的改进
用列表推导式一行实现函数功能
def caculate_num2(num):
return sum([i for i in range(1,num+1)])
print(caculate_num2(100))
>>>
5050
算法分析:sum()函数的参数是可迭代的对象
先将1~100放在列表里,然后用sum函数直接求和 时间复杂度 为1
比进行n次for循环要高效得多
这种写法适用于交互式编程
5.必须参数和关键字参数
- 1.必须参数必须以正确的方式传入,调用的时候必须和声明的时候顺序保持一致
def f(name,age):
print('My name is %s ,I am %d years old'%(name,age))
#name、age为必须参数
f("xzy",20)
>>>
My name is xzy ,I am 20 years old
f(20,"xzy")
>>>
My name is 20 ,I am xzy years old #语义错误,gg
- 2.使用关键字参数,调用函数的实际参数顺序可以与形参顺序不一致
python解释器可以根据参数名字匹配参数值
f(age=40,name='刘强东')
>>>
My name is 刘强东 ,I am 40 years old
- 3.默认参数 缺省参数没有传入,默认值会生效
函数的默认参数必须放在最后
def f2(name,age,sex='male'):
print('My name is %s ,I am %d years old,I am a %s' % (name, age,sex))
f2(name='刘强东',age=40) #是否显示指定参数,方便自己阅读为目的
>>>
My name is 刘强东 ,I am 40 years old,I am a male
6.不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。
基本语法如下:
def functionname([formal_args,],*var_args_tuple ):
函数体
return [expression]
加了星号(*)的变量名会存放所有未命名的变量参数。
不定长参数实例如下:
- 带*的参数表示元组
def printinfo( arg1, *vartuple ):
"打印任何传入的参数"
print("输出:")
print arg1
for var in vartuple:
print var
return;
# 调用printinfo 函数
printinfo( 10 );
printinfo( 70, 60, 50 );
>>>
输出:
10
输出:
70
60
50
变长参数
#将参数都放进一个元组中
def self_print(name,*a): # *a为元组
print("\n", type(a))
print(name,a)
self_print("xzy",1,2,3,4,5,6)
>>>
<class 'tuple'>
xzy (1, 2, 3, 4, 5, 6)
- **的参数表示字典
def d_self_print(**name):
"""将参数都放进字典中"""
print(name)
d_self_print(last_name="刘",first_name="强东")
>>>
{'last_name': '刘', 'first_name': '强东'}
- 用参顺序:位置参数->元组->字典
def mix(name,*t,**kw):
print(name)
print(t)
print(kw)
mix("zhangsan",20,"neuq",gender='female')
匿名函数
-
lambda表达式
语法:lambda 参数:表达式
冒号前面是参数,可以有多个
冒号后面是表达式,只能是一个表达式 不写return 返回值就是表达式的结果 - 优点:减少代码量,更优雅
实例1:
最简单的lambdu表达式:
def rect(x,y):
return x*y
ans=rect(4,5)
print(ans)
#使用lambda表达式有效地减少代码量:
res=lambda x,y:x*y
print(res(4,5))
>>>
20
20
实例2:
条件结构的lambda表达式:
def cal(x,y):
if x>y:
return x*y
else:
return x/y
cac=lambda x,y:x*y if x>y else x/y
实例3:
默认参数也能够在lambda参数中使用,就像在def中使用一样。
x = (lambda a="I", b="love", c="U": a + b + c)
x("I don't")
>>>
I don't love U
实例4:
列表排序中使用lambda表达式
-
复习 sotred()函数
描述:sorted() 函数对所有可迭代的对象进行排序操作。
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
sorted语法:
sorted(iterable[, cmp[, key[, reverse]]])
参数说明:
- iterable -- 可迭代对象。
- cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。
- key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
>>>a = [5,7,6,3,4,1,2]
>>> b = sorted(a) # 保留原列表
>>> a
[5, 7, 6, 3, 4, 1, 2]
>>> b
[1, 2, 3, 4, 5, 6, 7]
>>> L=[('b',2),('a',1),('c',3),('d',4)]
>>> sorted(L, cmp=lambda x,y:cmp(x[1],y[1])) # 利用cmp函数
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> sorted(L, key=lambda x:x[1]) # 利用key
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(students, key=lambda s: s[2]) # 按年龄排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(students, key=lambda s: s[2], reverse=True) # 按降序
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>>
关于sorted的用法,详情请参考https://www.runoob.com/python/python-func-sorted.html
进入正题
用lambda表达式进行列表排序:
#新建一个列表,列表中的每一个元素都是存储姓名、年龄信息的元组
stus=[
{'name':'zhangsan','age':33},
{'name':'lisi','age':12},
{'name':'wangwu','age':53},
{'name':'zhaoiu','age':18},
{'name':'tianqi','age':77}
]
print('排序前:',stus)
#以列表staus的元组元素的年龄对应的值为依据 从大到小排序
res = sorted(stus,key=lambda x: x['age'], reverse=True)
print('年龄排序后',res)
res = sorted(stus,key=lambda x: x['name'])
print('name排序后',res)
>>>
排序前 [{'name': 'zhangsan', 'age': 33}, {'name': 'lisi', 'age': 12}, {'name': 'wangwu', 'age': 53}, {'name': 'zaoliu', 'age': 18}, {'name': 'tianqi', 'age': 77}]
年龄排序后 [{'name': 'tianqi', 'age': 77}, {'name': 'wangwu', 'age': 53}, {'name': 'zhangsan', 'age': 33}, {'name': 'zaoliu', 'age': 18}, {'name': 'lisi', 'age': 12}]
name排序后 [{'name': 'lisi', 'age': 12}, {'name': 'tianqi', 'age': 77}, {'name': 'wangwu', 'age': 53}, {'name': 'zaoliu', 'age': 18}, {'name': 'zhangsan', 'age': 33}]
实战练习
统计《三国演义》中人物的出场次数,并绘制出相关的词云图
大概思路
- 准备工作:
在pycharm终端中输入命令安装相应的包
pip install jieba
pip install collections
pip install wordclude
加载头文件
import jieba #用来分词
from collections import Counter #用来计算词语出现的次数
from wordclude import Worldclude #用来生成词云分布图
- 1.读入threekingdom.txt文本
文件IO操作:https://www.runoob.com/python3/python3-file-io.html - 2.用结巴分词的.lcut()函数,将文本切割成一个一个的词语,存在一个集合words的数据结构里
- 3.便历words 将每一个词和出现的次数对应存入字典counts{}中,每出现一次,对应词语的值+1
- 4.用sorted()函数对字典的value(每个词出现的次数)为依据进行排序
- 5.将具有相同人物属性的关键词元素进行合并
- 6.去除类似"将军", "却说", "丞相", "二人", "不可", "荆州"这种与人物无关的字典元素
- 7.调用wordclude包中的函数,生成相应的词云字符串
#案例
#三国小说人物出场词频统计
import jieba
from collections import Counter
import WordCloud
def parse():
""" 三国小说人物出场词频统计 """
#定义无关词集合
excludes = {"将军", "却说", "丞相", "二人", "不可", "荆州", "不能", "如此", "商议",
"如何", "主公", "军士", "军马", "左右", "次日", "引兵", "大喜", "天下",
"东吴", "于是", "今日", "不敢", "魏兵", "陛下", "都督", "人马", "不知",
'玄德曰', '孔明曰', '刘备', '关公'}
with open('threekingdom.txt','r',encoding='utf-8') as f:
txt=f.read()
print(txt)
parse()
# # jieba分词
txt='我来到北京清华大学'
#讲字符串分割成等量的中文
seg_list=jieba.lcut(txt)
print(seg_list)
words=jieba.lcut(txt)
print(words)
counts={}
for word in words:
if len(word)==1:
continue
else:
#往字典里增加元素
counts[word]=counts.get(word,0)+1
#第一次出现,先得创建一个键值对,key为word value=0
print(counts)
counts['孔明']=counts.get('孔明')+counts.get('孔明曰')
counts['玄德']=counts.get('玄德')+counts.get('刘备')
counts['关公']=counts.get('关公')+counts.get('云长')
#删除字典中的无关词
for word in excluds:
del counts[word]
#统计出现名字最高的前20个词
items=list(counts.items())
print(items)
items.sort(key=lambda x:x[1],reverse=True)
print("排序后:",items)
for i in range(20):
character,count= items[i]
print(character, count)
#构造词云字符串
li=[]
for i in range(10):
character, count = items[i]
for _ in range(count):
li.append(character)
print(li)
cloud_txt=','.join(li)
print(cloud_txt)
wc=WordCloud(
background_color="white",
font_path="msyh.ttc",
#是否出现两个词的搭配 默认是True
collocations=False
).generate(txt)
wc.to_file('三国词云.png')