python函数编程
本章所讲内容:
5.1 函数定义
5.2 函数的调用
5.3 函数划分
5.4 匿名函数
5.5 作用域
5.1 函数定义知识点讲解
5.1.1 python 函数的定义
函数(function):是一个可以被重复调用的带有一个入口和一个出口的固定的程序段
函数的定义:(function) 代码块。计算机的函数,是一个固定的一个程序段,或称其为一个子程序,它在可以实现固定运算功能的同时,还带有一个入口和一个出口,所谓的入口,就是函数所带的各个参数,我们可以通过这个入口,把函数的参数值代入子程序,供计算机处理;所谓出口,就是指函数的函数值,在计算机求得之后,由此口带回给调用它的程序。
简单来说就是将我们要执行的代码进行结构的整合,形成可被调用的代码块
函数是可以重复调用的代码块
要想程序打得好,就要学会函数,函数在手天下我有,日出东方,唯我不败(要有自信哦)
函数的优点:
1、减少冗余代码
2、代码结构清晰
3、保持代码的一致性
函数编写:
语法:
def 函数名(参数):
代码块
return
1、关键字: def
2、函数名:
命名规范:
1、字母开头
2、不允许有关键字
3、不允许有特殊符号
4、不允许莫名其妙的函数名 a,b
5、参数:参数是定义在参数括号里,由调用时传入,作用在函数内部的变量
6、如果有参数,写在参照括号里
7、如果没有,写空括号
5.2 函数的调用
5.2.1 函数调用
函数在没有调用之前不会执行
函数名加括号,并且进行对应的传参的形式
在定义函数的参照括号内定义的参数 我们称之为 形参
在调用函数的时候我们传递值 我们称之为 实参
def func(a):
print('this is first test')
print(a)
func(18)
输出结果:
this is first test
18
5.3 函数的划分
按照参数类型划分:
位置参数
关键字参数
默认参数
参数组
5.3.1 位置参数
是我们在传参的时候,实参传递的顺序按照形参定义的顺序进行传递的传参方式。
def func(name,city):
print('i am %s,i am from %s'%(name,city))
func('xuegod','for')
func('for', 'xuegod')
输出结果:
i am xuegod,i am from for
i am for ,i am from xuegod
5.3.2 关键字参数
是我们在传参的时候,以形参等于实参的形式忽略形参定义的顺序进行传参的传参方式
因为 Python 解释器能够用参数名匹配参数值。
def func(name,city):
print('i am %s,i am from %s'%(name,city))
func(city='xuegod',name ='for')
func(name = 'for',city= 'xuegod')
输出结果:
i am for ,i am from xuegod
5.3.3 默认值参数、缺省参数(面试题)
是在我们定义参数时候,我们给形参一个默认值,在我们调用函数的时候,如果不给有默认值的形参传参,会自动采用默认值。
def func(name,city='beijing'):
print('i am %s,i am from %s'%(name,city))
func(name = 'for')
func(city='xuegod',name = 'for')
输出结果:
i am for ,i am from beijing
i am for ,i am from xuegod
注意:默认值参数必须写在正常参数的后面,
错误示范:
def func(city='beijing',name):
print('i am %s,i am from %s'%(name,city))
输出结果:
def func(city='beijing',name):
^
SyntaxError: non-default argument follows default argument
5.3.4 参数组(不定长参数 面试)
处理比当初声明时更多的参数,会将传入的参数变成元组(*args)或者字典(**kwargs),声明的时候不用命名
- 元组参数组
通过给形参前面添加*使参数变成一个元组,所有传递的参数变成元组的元素
def say_hello(*args):
print(args)
say_hello()
say_hello(1)
say_hello(1,2,3,4,5)
运行结果如下:
()
(1,)
(1,2,3,4,5)
- 字典参数组
通过给形参前面添加**使参数变成一个字典,所有传递的参数变成字典的键值对,这里传参要求键等于值的形式。
def say_hello(**kwargs): print(kwargs) say_hello() say_hello(a=1) say_hello(a=1,b=2,c=3)
运行结果如下:
{}
{‘a’: 1 }
{‘a’:1,’c’:3,’b’:2}
案例:
def fun_test(*args,**kwargs): a = args b = kwargs print(a,b) fun_test(1,2,a=1)
运行结果如下:
(1, 2) {'a': 1}
- 不定长参数在python2和python3 的区别
Python2:
def say_hello(b=1,*arg,**kwargs):
print arg
python3:
def say_hello(*arg ,a=1,**kwargs):
print(arg)
在python2中参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。而python3中却可以可变参数写在默认参数前面。
5.4 匿名函数lambda(面试)
在定义函数的时候,不想给函数起一个名字。这个时候就可以用lambda来定义一个匿名函数。
语法:lambda 参数:表达式(block)
5.4.1 lambda 参数:表达式(block)
参数:可选,通常以逗号分隔的变量表达式形式,也就是位置参数
表达式:不能包含循环、return,elif ,可以包含if.
>>> L = lambda x: x*x
>>>print(L(5))
25
>>> L = lambda x : ‘x>10’ if x > 10 else ‘x<10’
>>> print (L(5))
x<10
不支持return
>>>L= lambda x: return 'x>10' if x>10 else 'x<10'
错误示范:
>>> File "<input>", line 1
L= lambda x: return 'x>10' if x>10 else 'x<10'
^
SyntaxError: invalid syntax
注意:在python2中lambda 不支持print,但在python3中支持print()
例子:
比如现在要对一个列表中的元素进行平方
那平方之前我们先讲一个map函数
1、map()
map () 是python的内置函数,它接受一个函数和一个可迭代对象,并且通过函数依次作用在可迭代对象的每个元素上,得到一个新的对象。
这个是普通函数的写法
def func(x):
return x*x
a = (map(func,[1,2,3]))
for i in a:
print(i,end=’’)
#list(a)
输出结果:
1 4 9
看用lambda怎么写
b = map(lambda x:x*x,[1,2,3])
for i in b:
print(i)
输出结果:
1 4 9
注意:
Python2 中
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> c = map(lambda x,y:x+y,a,b)
>>> c
[5, 7, 9]
>>>
Python3 中
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> c = map(lambda x,y:x+y,a,b)
>>> c
<map object at 0x0000020B168B7668>
>>>
>>> print(list(c))
[5, 7, 9]
>>>
>>> print(list(c))
[]
为什么为空呢?
上面的元素已经一个个的遍历完了,并不会再次重复遍历。并且没有一个变量承载,所以就为空了。
注意:即使lambda简洁好用,但是不建议大家用,工作中也很少用.
1、好多人觉得方便,容易滥用;
2、用多了,程序可读性很差;
3、每个人对抽象层级的接受和忍耐不同;
2、zip()
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
zip 方法在 Python 2 和 Python 3 中的不同:在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。如需展示列表,需手动 list() 转换。
a = [1,2,3,4]
b = [5,6,7,8]
#压缩
c = zip(a,b)
print(list(c))
print(list(c))
运行结果如下:
[(1, 5), (2, 6), (3, 7), (4, 8)]
[]
实战:重写zip()方法
5.5 作用域
5.5.1 变量起作用的范围
Python2.4版本及以前
L local局部作用域,本地作用域
G global全局作用域
B built-in内建作用域
Python2.4之后(包括python3)
L local局部作用域,本地作用域
E enclosing嵌套作用域
G global全局作用域
B built-in内建作用域
for,if,while这些流程控制不会形成自己的作用域
import sys
#内键作用域
print(dir())
#全局作用域,全局变量
name = 'while'
def hello():
#嵌套作用域
name = 'for'
def hi():
#本地作用域,局部变量
age = 18
print(name)
print(age)
hi()
hello()
什么叫局部变量,全局变量?
局部变量是指在程序中只在特定过程或函数中可以访问的变量。
如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量
总结:
局部变量,就是在函数内部定义的变量。
不同的函数,可以定义相同的名字的局部变量,但是各用个的不会产生影响。
局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用。
5.5.2 声明全局变量
global声明全局变量
name = 'for'
print(name)
def Hello():
global name
name = name + 'is cool'
print(name)
Hello()
print(name)
输出结果:
for
Foris cool
foris cool
在学习作用域的过程当中我们要认识到变量查找遵循就近原则,由内到外的查找。
总结:
在函数外边定义的变量叫做全局变量
全局变量能够在所有的函数中进行访问
如果在函数中修改全局变量,那么就需要使用global进行声明,否则出错
如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的,小技巧强龙不压地头蛇
注意:如果c是一个列表,字典这些可变的类型的数据。那还要声明global?
解答:如果是类型的数据,不用声明global。
c = [1,2,3]
d ={}
e =set()
def test01():
c.append('5')
d.update({'name':'for'})
e.add(1)
test01()
print(c,d,e)
总结:
在函数中不使用global声明全局变量时不能修改全局变量的本质是不能修改全局变量的指向,即不能将全局变量指向新的数据。
对于不可变类型的全局变量来说,因其指向的数据不能修改,所以不使用global时无法修改全局变量。
对于可变类型的全局变量来说,因其指向的数据可以修改,所以不使用global时也可修改全局变量。
拓展:偏导数
应用场景:函数在执行时,要带上所有必要的参数进行调用。然后,有时参数可以在函数被调用之前提前获知。这种情况下,一个函数有一个或多个参数预先就能用上,以便函数能用更少的参数进行调用。
import functools
def add(a, b):
return a + b
add(4, 2)
#利用偏导数给一个固定值
plus3 = functools.partial(add, 3)
plus5 = functools.partial(add, 5)
plus3(2)
plus5(3)
实战:python 利用 函数直接进行爬取糗事百科图片,并保存到本地。(小伙伴拿到代码就可运行 qq:3440037784)
import requests
from lxml import etree
headers = {
'Accept': 'text/html, application/xhtml+xml, image/jxr, */*',
'Accept - Encoding': 'gzip, deflate',
'Accept-Language': 'zh-Hans-CN, zh-Hans; q=0.5',
'Connection': 'Keep-Alive',
'Host': 'www..com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'
}
def get_image(n,m):
for i in range(n,m+1):
request_url='https://www.qiushibaike.com/imgrank/page/%s/'%str(i)
response = requests.get(request_url,headers).content
xpath_content = etree.HTML(response)
images_url = xpath_content.xpath('//*[@class="thumb"]//a/img/@src')
print(images_url)
save_image(images_url)
def save_image(images_url):
for i in images_url:
new_url = 'http:'+ i
print(new_url)
filename = new_url[-1:-6:-2]+'.png'
img_data = requests.get(new_url).content
with open(filename,'wb') as f:
f.write(img_data)
get_image(2,3)
结果展示注明:由于图片太多只展示一张,略表敬意。