#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 函数的作用:
# 1.代码重用
# 2.流程分解
# 例1:函数的定义和调用
def bar():
print('hello world')
bar()
# 例2:函数参数
2.1 形参与实参
def add(x,y): #x,y是形参
print (x+y)
add(3,5) #3,5是实参
2.2参数顺序
def people(name,age):
print ('Name:',name)
print ('Age:',age)
people('Tom',23) #参数的传入是有顺序的。形参与实参的顺序要一一对应
2.3关键字参数
def people(name,age):
print ('Name:',name)
print ('Age:',age)
people(age=12,name='Bob')
2.4默认参数
def people(name,age,sex='boy'):
print ('Name:',name)
print ('Age:',age)
print ('Sex:',sex)
people('Tom',23)
2.4不定长参数
>>> def bar(*arg):
... print(arg)
...
>>> bar(1,2,3)
(1, 2, 3)
2.5**kwargs 接收键值对参数
>>> def bar(**kwargs):
... print (kwargs)
...
>>> bar(name='Tom',age=18)
{'name': 'Tom', 'age': 18}
2.6参数的位置
>>> def bar(name,age,sex='boy',*args,**kwargs):
... print(name,age,sex,args,kwargs)
Tom 18 1 (2, 3, 4) {'city': "xi'an"}
>>> bar('Tom',18,1,2,3,4,city="xi'an")
Tom 18 1 (2, 3, 4) {'city': "xi'an"}
>>> bar('Tom',18,'boy',1,2,3,4,city="xi'an")
Tom 18 boy (1, 2, 3, 4) {'city': "xi'an"}
# 例3:函数的多态
def add(x,y):
print (x+y)
add(3,5)
add('hello','world')
# 例4:嵌套函数
def bar():
def foo():
print("hello world")
foo()
bar()
# 例5:作用域法则LEGB
# L-Local(function);函数内的名字空间
# E-Enclosing function locals;外部嵌套函数的名字空间(例如closure)
# G-Global(module);函数定义所在模块(文件)的名字空间
# B-Builtin(Python);Python内置模块的名字空间
# 例6:global语句
x = 88
def bar():
global x
x = 99
bar()
print (x)
# 例7:nonlocal ————用于嵌套函数中
def bar():
x = 1
def foo():
nonlocal x
x += 1
foo()
print(x)
bar()
# 例8:闭包(closure):在一个内部函数对在外部的作用的作用域进行一个引用,那么内部函数就是一个闭包
>>> def maker(N):
... def action(X): #一个内部函数
... return X ** N #N为上级函数的一个变量
... return action
...
>>> f = maker(2)
>>> f
<function maker.<locals>.action at 0x000002C47A1E2A60>
>>> f(3)
闭包的三个特点:
1.闭包函数必须有内嵌函数
2.内嵌函数需要引用该嵌套函数上一级namespace中的变量
3.闭包函数必须返回内嵌函数
# 例9:函数的返回值
9.1 默认返回None
>>> def bar():
... print ("hello")
...
>>> f = bar()
hello
>>> print(f)
None
9.2 指定返回值
>>> def bar():
... print("hello")
... return 1
...
>>> f = bar()
hello
>>> print(f)
1
9.3 返回计算结果
>>> def bar(x,y):
... return x + y
...
>>> f = bar(1,2)
>>> print(f)
3
9.4 结束函数
>>> def bar():
... print("hello")
... return 1
... print("world")
>>> bar()
hello
1
9.5 返回元组
>>> def bar(x,y):
... return x,y
...
>>> bar(1,2)
(1, 2)
return的作用:
1.结束函数
2.返回某个对象
# 例10:三元函数
>>> print('hello') if True else False
hello
# 例11:高阶函数
11.1 变量名可以指向函数
>>> abs(-10)
10
>>> f = abs
>>> f(-10)
10
11.2 函数名可以作为其他函数的参数
>>> def bar(x,y,f):
... return f(x)+f(y)
...
>>> bar(-5,-3,abs)
8
11.3 函数名可以作为返回值
>>> def bar():
... def foo():
... return "hello"
... return foo
...
>>> bar()
<function bar.<locals>.foo at 0x00000194EED32A60>
# 例12:装饰器(Decorator):1.在代码运行期间增加功能;2.不改变源代码
1.在运行期间增加新功能
def hello():
print("hello")
def show_time(func):
print("------------")
func()
print("------------")
show_time(hello)
# 或者如下
# hello = show_time(hello)
# hello
# 但调用方式还是发生了改变
但是这样改变个源函数的调用方式
2.让hello接收函数名
#如果把一个函数名赋值给hello,hello()就可以执行函数了,
#关键问题是如何让show_time(hello)作为函数名赋值给hello
#想想高阶函数中函数名可以作为返回值返回的特性
#可以吧上述的函数改为如下
def hello():
print("hello")
def show_time(func):
def inner():
print("------------")
func()
print("------------")
return inner #此时如果调用show_time,返回的就是inner函数的函数名
hello=show_time(hello) #将inner函数赋值给hello
hello() #实际执行的是inner函数
3.@bar
#在python中hello=show_time(hello)可以写为@show_time,如下:
def show_time(func):
def inner():
print("------------")
func()
print("------------")
return inner
@show_time
def hello():
print("hello")
hello()
4.装饰器的参数
def show_time(func):
def inner(name):
print("------------")
func(name)
print("------------")
return inner
@show_time
def hello(name):
print("hello",name)
hello('Bob')
5.函数中嵌套装饰器
import time
def logger(flag=''):
def show_time(func):
def inner(*args,**kwargs):
start = time.time()
time.sleep(1)
func(*args,**kwargs)
end = time.time()
print('running time:',end - start)
if flag == 'true':
print('this is loggger')
return inner
return show_time
@logger('true')
def foo(*args,**kwargs):
sums = 0
for i in args:
sums += i
print(sums)
@logger()
def bar():
print('bar..')
foo(1,2,3)
bar()
6.6 源函数名称的问题————functools.wraps的作用
def show_time(func):
def inner(name):
print("------------")
func(name)
print("------------")
return inner
@show_time
def hello(name):
print("hello",name)
print(hello.__name__)
>>inner
源函数的名称变成了inner,不是原来的hello,通过引入wraps解决这个问题
改进如下:
from functools import wraps
def show_time(func):
@wraps(func)
def inner(name):
print("------------")
func(name)
print("------------")
return inner
@show_time
def hello(name):
print("hello",name)
print(hello.__name__)
>>hello
6.7装饰器实例
import sys
from functools import wraps
USERNAME, PASSWORD = 'root','123'
no_login = True
def login(func):
@wraps(func)
def inner(*args,**kwargs):
global no_login
if no_login:
print('您还没有登录,请登录---')
username = input('username:').strip()
password = input('password:').strip()
if USERNAME == username and PASSWORD == password:
no_login = False
else:
print('user or password is wrong !')
sys.exit()
func(*args, **kwargs)
return inner
@login
def home():
print('恭喜来到京东主页')
@login
def phone():
print('这里是手机专卖')
@login
def book():
print('这里是图书商店')
main = """
1.home
2.phone
3.book
请选择要进入的主页
"""
while True:
print(main)
choice = input(">>:").strip()
if choice == '1':
home()
elif choice == '2':
phone()
elif choice == '3':
book()
else:
sys.exit()
总结:装饰器三要素:LEGB、高阶函数、闭包