函数

函数

为何使用函数

  1. 组织结构混乱,可读性差
  2. 代码冗余
  3. 无法统一管理,维护难度极大

具备某一功能的工具即函数

函数的使用的必须遵循:先定义,后调用

函数分类:

1 内置函数:

python解释器自带的函数,python解释器启动就会定义好这些函数

len()
max()
min()
sum()

2 自定义函数:

语法:
# def 函数名(参数1,参数2,...):
# """注释"""
# 函数体
# return 返回值
定义阶段:
def tell_tag():
print('===========')

def tell_msg(msg):
print(msg)
调用阶段
tell_tag()
tell_tag()
tell_msg('hello world')
tell_tag()
tell_tag()
# func()

print(tell_msg)

'''
===========
===========
hello world
===========
===========

'''

总结

函数在定义阶段,只检测语法,不执行代码

1.函数的使用必须遵循:先定义,后调用

2.函数的定义,就相当于在定义一个变量,如果没有定义而直接调用,就相当于在引用一个不存在的变量名

# #定义阶段
# def foo():
# print('from foo')
# bar()
#
# #调用阶段
# foo()

 

# #定义阶段
# def bar():
# print('from bar')
# def foo():
# print('from foo')
# bar()
#
# #调用阶段
# foo()

 

#定义阶段
def foo():
print('from foo')
bar()

def bar():
print('from bar')
#调用阶段
foo()

函数定义的三种形式

无参
def main():
while True:
user=input('>>: ').strip()
# if len(user) == 0:continue
if not user:continue
password=input('>>: ')
res=auth(user,password)
if res:
print('login successful')
else:
print('logon err')
有参

函数体的代码,需要外部传入的值

def auth(user,pwd):
if user == 'egon' and pwd == '123':
return True
else:
return False

main()

def my_max(x,y):
if x > y:
return x
else:
return y

res=my_max(1,3)
print(res)
空函数
def select(sql):
'''
查询功能
:param sql: 格式后的sql
:return: xxxx
'''
pass

def update():
pass

def insert():
pass

def delete():
pass

调用函数

1 调用函数:函数名(),

需要注意:
先通过名字找到函数的内存地址,然后加括号调用

2 函数的返回值return

注意的第一点:
1.在调用函数的过程中,一旦执行到return,就会立刻终止函数,并且把return后的结果当做本次调用的返回值返回
2.函数体内可以有多个return,但是只能执行一次

# def foo():
# print('111')
# return 1
# print('2222')
# return 2
# print('3333')
# return 3
#
# res=foo()
# print('函数调用完毕',res)

注意的第二点:
返回的值,可以是任意类型

注意的第三点:

  1. 没有return:默认返回None
  2. 可以返回一个值===>值
  3. 可以用逗号分隔,返回多个值===>tuple
# def foo():
# return None
#
# res=foo()
# print('函数调用完毕',res,type(res))

函数的参数

1:形参与实参

形参:在函数定义阶段,括号内定义的参数的称为形参,就相当于变量名
实参:在函数调用阶段,括号内定义的参数的称为实参,就相当于变量值
在调用阶段,实参的值会绑定给形参,在调用结束后,解除绑定


def foo(x,y): #x=1,y=2
print(x,y)

foo(1,2)

参数的分类:

一:位置参数

位置形参:必须被传值的参数,多一个不行,少一个也不行
位置实参:从左到右依次赋值给形参

# def foo(x,y):
# print(x,y)
#
# foo(1,2)
二:关键字参数:

在函数调用阶段,按照key=value的形式定义实参
可以不依赖位置而指名道姓地给形参传值
需要注意的问题(可以与位置实参混用,但是):

  1. 位置实参必须在关键字实参的前面
  2. 不能为一个形参重传值
def foo(x,y):
print(x,y)

foo(1,2,y=20)
三:默认参数:

在定义函数阶段,已经为形参赋值了,在定义阶段已经赋值,意味着在调用阶段
可以不传值
注意的问题:

1 默认参数的值,只在定义时赋值一次
2 位置形参应该在默认参数的前面
3 默认参数的值应该是不可变类型

def foo(x,y=10):
print(x,y)


foo(y=11,x=1)


def register(name,age,sex='male'):
print(name,age,sex)


register('egon',18)
register('wsb',18)
register('alex',38,'xxxxxx')


x='male'
def register(name,age,sex=x):
print(name,age,sex)

x='female'
register('alex',18)


def register(name,sex='male',age):
print(name,age,sex)

四:可变长参数

实参可变长度指的是:实参值的个数是不固定
而实参的定义形式无非两种:

1、位置实参
2、关键字实参

针对这两种形式的实参个数不固定,相应的,形参也要有两种解决方案
针对按照位置定义的溢出的那部门实参,形参:*args

def func(x,y,z,*args): #args=(4,5,6)
print(x,y,z)
print(args)

func(1,2,3)
func(1,2,3,4,5,6)
func(1,2,3,*[4,5,6]) #func(1,2,3,4,5,6)
func(*[1,2,3,4,5,6]) #func(1,2,3,4,5,6)

func([1,2,3,4,5,6]) #func(1,2,3,4,5,6)


def func(x,y,z):
print(x,y,z)

l=[1,2,3]
func(*l)

针对按照关键字定义的溢出的那部分实参,形参:**kwargs

def foo(x,y,**kwargs): #kwargs={'a':1,'z':3,'b':2}
print(x,y)
print(kwargs)

foo(y=2,x=1,z=3,a=1,b=2)
foo(1,2,3,z=3,a=1,b=2)

foo(y=1,x=2,**{'a':1,'b':2,'c':3}) #foo(x=2,y=1,c=3,b=2,a=1)
foo(**{'x':1,'a':1,'b':2,'c':3}) #foo(x=1,c=3,b=2,a=1)

def foo(x,y,z):
print(x,y,z)

dic={'x':1,'y':3,'z':1}
foo(**dic) #foo(x=1,y=3,a=1)



def home(name,age,sex):
print('from home====>',name,age,sex)

def wrapper(*args,**kwargs): rgs=(1,2,3,4,5,6,7),kwargs={'c':3,'b':2,'a':1}
home(*args,**kwargs)
# home(*(1,2,3,4,5,6,7),**{'c':3,'b':2,'a':1})
#home(1,2,3,4,5,7,a=1,b=2,c=3)



# wrapper(1,2,3,4,5,6,7,a=1,b=2,c=3)
wrapper('egon',sex='male',age=19)
五:命名关键字参数(了解):

形参中,在*后定义的参数称之为命名关键字参数,
它的特性是:传值时,必须按照关键字实参的形式传值

# def foo(x,y=20,*args,a=1,b):
# print(x,y,a,b)

# # foo(10,b=3)
# foo(10,22,33,44,a=2,b=3)

位置参数,默认参数,*args,命名关键字参数,**kwargs

Other

函数是第一类对象:函数可以当做数据来使用

def foo():
print('from foo')

可以被引用

f=foo
# print(f)
f()

可以当做参数传入一个函数

def wrapper(x):
# print(x)
x()
wrapper(foo)

可以当做函数的返回值

def wrapper():
return foo

f=wrapper()
print(f is foo)

可以当做容器类型的一个元素

# l=[foo,1,2]
# l[0]()

函数嵌套

1 函数的嵌套调用:在调用一个函数的过程中,又调用其他的函数

def my_max2(x,y):
if x > y:
return x
else:
return y


def my_max4(a,b,c,d):
res1=my_max2(a,b)
res2=my_max2(res1,c)
res3=my_max2(res2,d)
return res3

res=my_max4(1,2,3,4)
print(res)

2 函数的嵌套定义:在定义一个函数内部,又定义了一个函数

def f1():
def f2():
def f3():
print('from f3')
f3()
x=1
f2()
print(x)
f1()

# f2()
# print(x)

名称空间

存放名字与值绑定关系的地方

内置名称空间:

存放的是:内置的名字与值的绑定关系
生效:python解释器启动
失效:Python解释器关闭

全局名称空间

存放的是:文件级别定义的名字与值的绑定
生效:执行python文件时,将该文件级别定义的名字与值的绑定关系存放起来
失效:文件执行完毕

局部名称空间

存放的是:函数内部定义的名字与值的绑定关系
生效:调用函数时,临时生效
失效:函数调用结束

加载顺序

先内置,再全局,最后局部
查找名字的顺序:先局部,再全局,最后内置

x=10
if x > 3:
y=2

def foo(a,b): #a='aaaa' b='bbbb'
m=11111
n=2222
def bar():pass

foo('aaaa','bbbb')


max=10
def f1():
max='f1'
def f2():
max='f2'
print(max)
f2()

# f1()
print(max)

作用域:

全局作用域:包含内置名称空间的名字与全局名称空间的名字
全局存活,全局有效

局部作用域:包含局部名称空间的名字
临时存活,局部有效

x=1011111111111111111111111111111111111111111 
def f1(a):
y='fffffffffffffffffffffffffffffff1'
print(locals())
print(globals())


print(globals())
print(dir(globals()['__builtins__']))

print(locals() is globals())


f1(12321312312312312312312312312312312312313213)

作用域关系

在函数定义时,就已经固定了,与调用位置无关

x=10000000000000000000000000
def f1():
def f2():
# x='123123123123123123123123123123123'
print(x)
return f2

f=f1()

# print(f)


def func():
x=123
f()
x='hello'
func()



global nonlocal
x=1
def f1():
global x
x=10
f1()
print(x)

 

x=1
def f1():
x=2
def f2():
nonlocal x
x=111111
f2()
print(x)

f1()
posted @ 2017-12-21 18:28  EiO  阅读(120)  评论(0)    收藏  举报
点我返回顶部