函数的初识和进阶

一、函数的初识

1、为什么要使用函数?

前言:

# 重复代码多
# 可读性差。
li = [1, 2, 3, 43, 'fdsa', 'alex']
count = 0
for i in li:
count += 1
print(count)

s1 = 'fdsgdfkjlgdfgrewioj'

count = 0
for i in s1:
count += 1
print(count)

直接结果:
6
19

2、def写len函数
2.1函数的定义:
'''
def 关键字 函数名(设定与变量相同):
函数体
'''

写个跟len相同的函数
s1 = 'fdsgdfkjlgdfgrewioj'
def my_len():
count = 0
for i in s1:
count += 1
print(count)

my_len() # 函数名+() 执行函数

2.2 函数的返回值return
#遇到return,函数结束
def func1():
print(11)
print(22)
return
print(333)
print(444)
func1()

执行结果为:
11
22

#给函数的调用者(执行者)返回值。
    无 return 返回None
return 不写 或者 None 返回None
return 返回单个数.
return 返回多个数,将多个数放在元组中返回。

#return单个返回
s1='hahahaha'
def my_len():
count=0
for i in s1:
count+=1
return 666
print(my_len(),type(my_len()))
#return返回多个
s1='hahahah'
def my_len():
count = 0
for i in s1:
count += 1
return 666,222,count,'老男孩'
print(my_len(),type(my_len()))
执行结果:(666, 222, 7, '老男孩') <class 'tuple'>

#
s1='hhaaha'
def my_len():
count=0
for i in s1:
count+=1
return 666,222,count
ret1,ret2,ret3=my_len() # (666, 222, 19,) 利用分别赋值

print(ret1)
print(ret2)
print(ret3)
执行结果:

666
222
6

#这个相当于用函数方式写的len函数
s1='hahahahah'
def my_len():
count = 0
for i in s1:
count += 1
return count
print(my_len()) #9
print(len(s1)) #9

3、函数的传参(形参和实参
li = [1, 2, 3, 43, 'fdsa', 'alex']
s1 = 'fdsgdfkjlgdfgrewioj'
def my_len(a): #函数的定义 ()括号里放的是形式参数,形参
count=0
for i in a:
count+=1
return count
ret=my_len(li) #函数的执行 ()括号里放的是实际参数,实参
print(ret)
print(len(li))

执行结果:
6
6

3.1、实参角度分为(位置参数、关键字参数、混合参数)
#位置参数:必须一一对应,按顺序
def func1(x,y):
print(x,y)
func1(1, 2)
执行结果:1 2

#关键字参数:必须一一对应,不分顺序
def func1(x,y,z):
print(x,y,z)
func1(y=2,x=5,z=1)

直接结果:5 2 1

练习1:判断a,b ,谁大输出谁
def max(a,b):
if a > b:
return a
else:
return b 中间部分可以写成:ret= a if a>b else b ,这个是三元表达式,为什么叫三元表达式,三个变量,ret、a、b
                      return ret
print(max(100,102)) #102

以上可以用底下代码实现:
def max(a,b):return a if a > b else b
print(max(100,102)) #102

#混合参数。一一对应且关键字参数必须在位置参数后面
def func2(argv1,argv2,argv3):
print(argv1)
print(argv2)
print(argv3)
func2(1,2,argv3=3)
执行结果:
1
2
3
3.2、形式角度(位置参数、默认参数、动态参数)
#位置参数:必须一一对应,按顺序

def func1(x,y):
print(x,y)
func1(1,2) #1 2

#默认参数:必须在位置参数后面
def register(name,sex='男'):
with open('register',encoding='utf-8',mode='a') as f1:
f1.write('{} {} '.format(name,sex))

while True:
username = input('请输入姓名:/q 或者 Q 退出')
if username.upper() == 'Q':break
if 'a' in username:
sex = input('请输入性别:')
register(username,sex)
else:
register(username)
执行:

请输入姓名:/q 或者 Q 退出张三
请输入姓名:/q 或者 Q 退出a丽丽
请输入性别:女
请输入姓名:/q 或者 Q 退出Q

最终register文件中:

张三 男
a丽丽 女

#动态参数 *args ,**kwargs万能参数
def func2(*args,**kwargs):
    print(args)  #元祖(所有位置参数)
print(kwargs)
func2(1,2,3,[1,2,5],'a',name='hha',age=12)
执行结果:

(1, 2, 3, [1, 2, 5], 'a')
{'name': 'hha', 'age': 12}

---------------------------------------------------------

def func3(a,b,*args,sex='男'):
print(a)
print(b)
print(sex)
print(args)
func3(1,2,'老男孩','alex','wusir',sex='女') #把默认参数改写了

执行结果:

1
2

('老男孩', 'alex', 'wusir')  

形式参数最终顺序:位置参数,*args,默认参数,**kwargs

def func3(a,b,*args,sex='男',**kwargs):
print(a)
print(b)
print(sex)
print(args)
print(kwargs)
func3(1,2,'老男孩','alex','wusir',name='alex',age=46)

执行结果:

1
2

('老男孩', 'alex', 'wusir')
{'name': 'alex', 'age': 46}

----------------------------------------------

def func1(*args,**kwargs):  # 函数的定义 * 聚合。
print(args)
print(kwargs)
l1 = [1,2,3,4]
l11 = (1,2,3,4)
l2 = ['alex','wusir',4]
func1(*l1,*l2,*l11) # 函数的执行:* 打散功能


执行结果:

(1, 2, 3, 4, 'alex', 'wusir', 4, 1, 2, 3, 4)
{}

-------------------------------
接着上面的:
func1(1,2,3,4,'alex','wusir',4,1,2,3,4)  # 函数的执行:* 打散功能。
执行结果:

(1, 2, 3, 4, 'alex', 'wusir', 4, 1, 2, 3, 4)
{}

----------------------------
接着最上面的:
dic1 = {'name1':'alex'}
dic2 = {'name2':'laonanhai'}
func1(**dic1,**dic2)

执行结果:

()
{'name1': 'alex', 'name2': 'laonanhai'}

二、函数的进阶

1、
#临时名称空间:临时名称空间,局部名称空间,存入函数里面的变量与值的关系,随着函数的执行结束,临时名称空间消失。

#名称空间:全局名称空间,局部名称空间,内置名称空间。
只要创建.py文件,内置名称空间会加载到内存中。
#作用域:
# 全局作用域:全局名称空间,内置名称空间。
# 局部作用域:局部名称空间

#加载顺序,取值顺序。
#加载顺序:内置名称空间 ----> 全局名称空间----> 局部名称空间(函数执行时)
#取值顺序:局部名称空间 ---> 全局名称空间 ----> 内置名称空间

name1 = 'wusir'
def func1():
print(name1)
def func2():
print('****',name1)
func2()
func1()
执行结果:

wusir
**** wusir

-------------------------------------------

name1 = 'wusir'
def func1():
name2 = 'laonanhai'
print(globals())
print(locals())
func1()
执行结果:

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000000025DB160>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/Administrator/PycharmProjects/untitled2/test.py', '__cached__': None, 'name1': 'wusir', 'func1': <function func1 at 0x0000000001CE2E18>}
{'name2': 'laonanhai'}

 
#关键字:global nonlocal

#global 1,声明一个全局变量
#2,更改一个全局变量
name = 'wusir'
def func1():
global name
name = 'alex' #把name值更改了
return
func1()
print(name)
执行结果:alex

#nonlocal
def func1():
name1 = 'alex'
print('+',name1)
def inner():
nonlocal name1
name1= 'wusir'
print('*',name1)
def inner1():
pass
inner()
print('%',name1)
func1()

执行结果:

+ alex
* wusir
% wusir

 备注:如果不加

 nonlocal name1
执行结果为:

+ alex
* wusir
% alex

2、函数名

2.1、可以互相赋值

def func1():
print(666)
f1 = func1
f1() #666

2.2、函数名可以当成函数的参数
def func1():
print(666)
def func2(argv):
argv()
print(777)
func2(func1)
执行结果:
666
777
2.3、可以当成容器类数据类型的参数
def func1():
print(666)

def func2():
print(777)

def func3():
print(888)

l1 = [func1, func2, func3]
for i in l1:
i()
2.4、函数名可以当成函数的返回值
def func1():
print(666)

def func2(argv):
print(777)
return argv

ret = func2(func1)
ret()
执行结果:
777
666
3、闭包
# 闭包 内层函数对外层函数非全局变量的引用,叫做闭包
#闭包的好处:如果python 检测到闭包
# 他有一个机制,你的局部作用域不会随着函数的结束而结束。
def wrapper():
name1 = '老男孩'
def inner():
print(name1)
inner()
wrapper() #老男孩

def wrapper():
name1 = '老男孩'
def inner():
print(name1)
inner()
print(inner.__closure__) # cell
wrapper()
执行结果:

老男孩
(<cell at 0x0000000001E17498: str object at 0x00000000022013F0>,)  出现这种cell的就是闭包

# 判断是不是闭包,出现None的不是闭包,出现cell那种的才是闭包
name1 = '老男孩'
def wrapper():
def inner():
print(name1)
inner()
print(inner.__closure__) # None
wrapper()
执行结果:

老男孩
None

name = 'alex'
def wrapper(argv):
def inner():
print(argv)
inner()
print(inner.__closure__) # cell
wrapper(name)
执行结果:

alex
(<cell at 0x0000000002147498: str object at 0x000000000210B228>,)

3、小型的网站爬虫

from urllib.request import urlopen
def index():
url = "http://www.cnblogs.com/jin-xin/articles/8259929.html"
def get():
return urlopen(url).read()
return get
name1 = 'alex'
content1 = index()()
content2 = index()()
print(content1)

执行结果:
网站的类似这种的

 3、装饰器

3.1、
def wrapper():
def inner():
name1 = 'alex'
print(name1)
inner()
wrapper()

执行结果:alex

def wrapper():
def inner():
name1 = 'alex'
print(name1)
return inner
ret = wrapper() # wrapper() 这个相当于inner
ret() #alex


装饰器例子2:
'''
# f = func1
# func1 = timer
#
# func1(f) # timmer(func1)
'''
# func1 = timer(func1) # inner
# func1() # inner()
import time

# @
def timer(f1): # f1 = func1
def inner():
start_time = time.time()
f1()
end_time = time.time()
print('此函数的执行效率%s' %(end_time-start_time))
return inner

@timer # func1 = timer(func1)
def func1():
print('晚上回去吃烧烤....')
time.sleep(0.3)
@timer # func2 = timer(func2)
def func2():
print('晚上回去喝啤酒....')
time.sleep(0.3)
func1() # inner()

执行结果:

晚上回去吃烧烤....
此函数的执行效率0.30101704597473145

#装饰器:在不改变原函数即原函数的调用的情况下,
# 为原函数增加一些额外的功能,打印日志,执行时间,登录认证等等。
3.2、被装饰函数带参数
举例1:
import time
def timer(f1): # f1 = func1
def inner(*args,**kwargs):
start_time = time.time()
f1(*args,**kwargs) # func1()
end_time = time.time()
print('此函数的执行效率%s' %(end_time-start_time))
return inner

@timer # func1 = timer(func1) inner
def func1(a,b):
print(a,b)
print('晚上回去吃烧烤....')
time.sleep(0.3)
func1(111,222) # inner(111,222)

执行结果:

111 222
晚上回去吃烧烤....
此函数的执行效率0.3000171184539795





举例2:
import time

def timer(f1): # f1 = func1
def inner(*args,**kwargs):
start_time = time.time()
ret = f1(*args,**kwargs) # func1()
end_time = time.time()
print('此函数的执行效率%s' %(end_time-start_time))
return ret #如果这个注释掉,返回的666的值就是None
return inner

@timer # func1 = timer(func1) inner
def func1(a,b):
print(a,b)
print('晚上回去吃烧烤....')
time.sleep(0.3)
return 666
ret2 = func1(111,222) # inner(111,222)
print(ret2)

执行结果为:

111 222
晚上回去吃烧烤....
此函数的执行效率0.3080177307128906
666

装饰器总结:

def wrapper(f1):
def inner(*args,**kwargs):
'''执行函数之前的操作'''
ret = f1(*args,**kwargs)
'''执行函数之后的操作'''
return ret
return inner

@wrapper
def func1():
print(222)
return 333
print(func1())

执行结果:
222
333



作业:
1),启动程序,首页面应该显示成如下格式:
欢迎来到博客园首页
1:请登录
2:请注册
3:文章页面
4:日记页面
5:评论页面
6:收藏页面
7:注销
8:退出程序
2),用户输入选项,3~6选项必须在用户登录成功之后,才能访问成功。
3),用户选择登录,用户名密码从register文件中读取验证,三次机会,没成功则结束整个程 序运行,成功之后,
可以选择访问3~6项.
4),如果用户没有注册,则可以选择注册,注册成功之后,可以自动完成登录,然后进入首页选择。
5),注销用户是指注销用户的登录状态,使其在访问任何页面时,必须重新登录。
6),退出程序为结束整个程序运行。

'''
 












 






 
 








































原文地址:https://www.cnblogs.com/lucky-penguin/p/8883364.html