首页 > 其他 > 详细

10.函数的基本使用

时间:2020-12-29 00:08:32      阅读:31      评论:0      收藏:0      [点我收藏+]
  • 引子
  • 函数的基本使用

  • 先定义,后调用

  • 定义函数的三种形式

  • 调用函数的三种形式

  • 函数的返回值

  • 函数参数的使用

  • 形参系列

  • 实参系列

  • 可变长系列


函数的基本使用


  • 什么是函数?

    ps:函数就是盛放代码的容器

    具备某一功能的工具--->函数

    事先准备工具的过程--->函数的定义

    遇到应用场景拿来就用--->函数的调用

    函数的使用原则:

    先定义   
    后调用  
  • 为何要用函数?

    解决下述问题:

    1.代码组织结构不清晰、可读性差
    2.可维护性、可扩展性差
  • 如何用函数?

    ? 先定义

    ? 三种定义方式

    ? 后调用

    ? 三种调用方式

    ? 返回值

    ? 三种返回值的形式

    定义的语法:
def 函数名(参数1,参数2,参数3,...):
	‘‘‘函数的文档注释‘‘‘
    函数体(代码1)
    代码2
    代码3
    return 返回值

# def: 定义函数的关键字;
# 函数名:函数名指向函数内存地址,是对函数体代码的引用。函数的命名应该反映出函数的功能;
# 括号:括号内定义参数,参数是可有可无的,且无需指定参数的类型;
# 冒号:括号后要加冒号,然后在下一行开始缩进编写函数体的代码;
# """文档注释""": 描述函数功能,参数介绍等信息的文档,非必要,但是建议加上,从而增强函数的可读性;
# 函数体:由语句和表达式组成;
# return 值:定义函数的返回值,return是可有可无的。

  • 一、定义函数、

定义函数发生的事情

1、申请内存空间把函数体代码放进去

2、将函数内存地址绑定给函数名

强调:定义函数只检测语法,不执行代码

def login():  # login = 函数的内存地址
    print(111)   # 函数体代码
    print(222)
    print(333)
    print(444)
    
x = 10       # x = 10的内存地址
print(x)     # 原则上打印应该返回内存地址,但是返回的是值。变量名受到python解释器特殊照顾由内存地址直接找到返回值打印。
print(login) # 但函数名不同,打印显示的是内存地址。定义函数的目的是为了把代码丢到容器,只需要运行不需查看。则无需被照顾。
  • 二、调用函数

调用函数发生的事情:

1、先通过函数名定为到函数的内存地址

2、函数内存地址()--->触发函数体代码的运行

强调:调用函数才会执行函数体代码

def login():
    print(111)   
    print(222)
   
login()  


# 例1
def func():
    print(11111   # 语法错误 定义阶段都无法通过


# 例2:
def func():
    print(1111)
    x            # 逻辑错误,x 没有定义,变量名也需要先定义后引用
    print(2222)

func()


# 例3:
# ================
def bar():
    print(‘from bar‘)

def foo():
    print(‘from foo‘)
    bar()

foo()
================
# 例4:         
def foo():
    print(‘from foo‘)
    bar()
          
foo()               # 语法错误,bar没有定义,调用肯定出错
          
def bar():
    print(‘from bar‘)

  • 三、定义函数的三种形式

1.无参函数
# 例1:函数体不需要外部传参数进行,它本身代码就是固定的,所以就是无参函数
def say():
    print(‘========‘)
    print(‘welcome to here‘)
    print(‘========‘)
say()

# 参数是函数的调用者向函数体传值的媒介,有参无参是根据函数体代码去走的,看函数体代码是否需要外部传参数
def login():
    inp_name = input("username>>>: ").strip()  
    inp_pwd = input("password>>>: ").strip()
    if inp_name == "egon" and inp_pwd == "123":
        print(‘login successful‘)
    else:
        print("username or password error")

login()  # 直接调用无需传参数,input功能已经实现与用户交互
2.有参函数
# 函数体代码需要外部传参数进行,这种函数就需要定义为有参函数
def max2(x,y):  # 参数---》原材料 
    if x > y:
        print(x)
    else:
        print(y)
max2(10,20)

3.空函数
# 函数体为pass代表什么都不做,称之为空函数。定义空函数通常是有用的,因为在程序设计的开始,往往是先想好程序都需要完成什么功能,然后把所有功能都列举出来用pass充当函数体“占位符”,这将使得程序的体系结构立见,清晰且可读性强。例如要编写一个程序,我们可能想到的功能有用户认证,下载,上传,等功能,可以先做出如下定义:

def auth_user():
    """user authentication function"""
    pass   # 代表占位符

def download_file():
    """download file function"""
    pass

def upload_file():
    """upload file function"""
    pass
  • 四、调用函数的三种形式

# 1.语句

len("hello")   # 单纯的调用,例如len统计hello的长度

# 2.表达式

res = len("hello")    # 将调用函数的返回值赋值给res

res = len("hello") * 10  # 将调用函数的返回值乘以10的结果赋值给res
print(res)

# 3 .可以当做参数传给另外一个函数
len("hello")             # 从形式上看就是将函数调用,从本质讲是跟2同理
print(len("hello"))      # 先调len的返回值然后再赋值给print
  • 五、函数的返回值

return详解:
def max2(x,y): 
    if x > y:
        return x
    else:
        return y
    
res = max2(10,20)
print(res)

# 1、return是一个函数结束的标志,函数可以有多个return,但只要执行一次return,整个函数就立即结束,并且将return后的值当做本次调用的结果返回:
def func():
    print("=====")  # 只运行到了此行
    return 111      # return后的值当做本次调用的结果返回  # 111
    print("****")
    return 222
    print("----------")
    return 333

res = func()
print(res)

# 2、return后的返回值有三种情况
# (1)return 值:返回的就是这一个值
# (2)return 值1,值2,值3:返回的一个元组
def func():
    return 111,"xxx",[22,33]

res = func()
print(res)   # (111,"xxx",[22,33])返回的是元组
# (3)函数内可以没有return、或者return None、或者return:返回的都是None
def func():
    print(111)
    return
    print(2222)


res = func()
print(res)

函数参数的使用

函数参数总体分为两大类:

1、形参:在函数定义阶段括号内指定的参数,称之为形式参数,简称形参----》变量名

2、实参:在函数调用阶段括号内传入的值,称之为实际参数,简称实参----》变量的值

形参与实参的关系是:
在调用函数时,实参值会绑定给形参名,在函数调用完毕后解除绑定
def func(x,y):    # x,y是形参,在定义阶段()内传值。形参指的是变量名。   
    print(x,y)
    
func(111,222)     # 111,222是实参,在调用阶段传送的值,实参指的是变量值
  • 形参系列:

  • 一、位置形参:在定义函数时,按照从左到右的顺序依次定义的变量名,称之为位置形参
    特点:每次调用必,须被赋值

def func(x,y): # 定义位置形参:x,y,两者都必须被传值
print(x)
print(y)

func(1,2) # 可以正常赋值,必须刚刚好
func(1,2,3) # 报错,多了一个值
func(1) # 报错,少了一个值


- ##### 二、默认形参:在定义函数时,就已经为某个形参赋值了,称之为默认形参

##### 				特点:调用函数时,可以不用为其赋值

```python
def func(name,age=18):     # age=18是默认形参,无需赋值,也可以被赋值
    print(name)
    print(age)
func("egon")       # name正常赋值
func("egon",19)       # 正常赋值

注意: 可以混用位置形参与默认形参,但是

1、位置形参必须在前面
def func(age = 18, name):
    print(name)
    print(age)        # 报错
2、默认形参的值通常应该是不可变类型
# 例一:
def func(name,hobby,hobbies = []): # 三次调用都用的是同一列表
    hobbies.append(hobby)
    print(‘%s的爱好是%s‘%(name,hobbies))
func(‘egon‘,‘read‘)     # egon的爱好是[‘read‘]
func(‘tom‘,‘play‘)      # tom的爱好是[‘read‘, ‘play‘]
func(‘jack‘,‘movie‘)    # jack的爱好是[‘read‘, ‘play‘, ‘music‘]

# 例二:
def func(name,hobby,hobbies = None):   # 设定hobbies为None
    if hobbies is None:         # 如果没有为hobbies传值,hobbies默认就是None
        hobbies = []            # 每次传值给hobbies,就会产生新的列表
    hobbies.append(hobby)
    print(‘%s的爱好是%s‘ %(name,hobbies))

func(‘egon‘,‘read‘)
func(‘tom‘,‘play‘)
func(‘jack‘,‘music‘)
func(‘lili‘,‘eat‘,["movie"])
3、默认形参的值是在函数定义阶段赋值的
m = 111
def func(x,y,z = m):   # 在定义阶段就把111赋值给了z
    print(x)
    print(y)
    print(z)
m = 666
func(1,2)
  • 实参系列:

  • 一、位置实参:在调用函数时,按照从左到右的顺序依次传入的值,称之为位置实参
    特点:按照位置为形参赋值,一一对应
def func(name,age):    # 定义位置形参:name,age,两者都必须被传值
    print(name)
    print(age)
    
func("egon")     # 报错,少了一个值
func("egon",19)  # 正常传值
  • 二、关键字实参:在调用函数时,按照key = value的形式传值,称之为关键字实参
    特点:可以打乱顺序,但是仍然能够指定道姓的为指定的形参赋值
def func(name,age):         # 定义位置形参:name,age,两者都必须被传值
    print(name)
    print(age)
    
func(age = 18,name = "egon")   # 正常传值

# 注意:可以混用位置实参与关键字实参,但是
# 1、位置实参必须在关键字实参的前面

func("egon",age = 18)    # 正常传值
func(age = 18,"egon")    # 报错,语法错误

# 2、不能为同一形参重复赋值

def foo(x,y,z):
    pass
foo(1,y=2,3)        # 报错,语法错误
foo(1,y=2,z=3,x=4)  # 报错,语法错误

  • 可变长系列

  • 可变长系列:

可变长参数指的是在调用函数时,传入的实参个数不固定,对应着必须有特殊形式的形参来接收溢出的实参
实参无非两种形式
溢出的位置实参----->*
溢出的位置关键字实参----->**

*与**在形参中是一种汇总行为

1、*在形参中的应用:*会将溢出的位置实参合并成一个元组,然后赋值给紧跟其后的那个形参名
def func(x,*y):   # *是接收位置溢出实参的功劳,不是y变量名的功劳。*后面可以跟任意变量名。
    print(x)
    print(y)
    
func(1,2,3,4,5)  #  x = 1 , y = (2,3,4,5)
# 1
# (2,3,4,5)

def func(x,*args):  # args变量名(译:参数) 通常搭配*使用 *args接收位置实参的溢出
    print(x)
    print(args)

func(1,2,3,4,5)  # 同上是一个道理


def my_sum(*args):  # 求和运算的函数
    res = 0
    for i in args:
        res += i
    print(res)

my_sum(1,2)
# 3
2、**在形参中的应用:**会将溢出的关键字实参合并成一个字典,然后赋值给紧跟其后的那个形参名
def func(x,**kwargs):  # kwargs = {"a":2,"c":4,"b":3}
    print(x)
    print(kwargs)

func(1,a=2,b=3,c=4)
# 1
# {‘a‘: 2, ‘b‘: 3, ‘c‘: 4}

=*与**在实参中是一种打散行为===

*在实参中的应用:*后可以跟可以被for循环遍历的任意类型,*会将紧跟其后的那个值打散成位置实参
def func(x,y,z):
    print(x)
    print(y)
    print(z)


func([11,22,33])      # 报错
func(*[11,22,33])     # func(11,22,33) *会把列表这种实参打散成位置实参
func(*"hello")        # func("h","e","l","l","o") 报错,但能证明*的打散行为
func(*{"k1":111,"k2":2222})  # func("k1","k2") 报错,但证明*能把字典打散成key

**在实参中的应用:**只能跟字典类型,**会将字典打散成关键字实参
func(**{"k1":111,"k2":2222})  # func(k2=2222,k1=111) 报错,没有k关键字,打散后对应不上

func(**{"x":111,"y":2222,"z":333})  # **将字典打散成关键字实参
# 111
# 2222
# 333

# 例1:
def wrapper(*args, **kwargs):   # 形参中带*和**是一种汇总行为
    print(args)
    print(kwargs)

wrapper(1,2,3,4,5,6,a=1,b=2,c=3)
# (1, 2, 3, 4, 5, 6)
# {‘a‘: 1, ‘b‘: 2, ‘c‘: 3}

# 例2:
def index(x,y,z):
    print(x,y,z)

def wrapper(*args,**kwargs):  
    index(*args,**kwargs)   # 实参中带*和**是一种打散行为
                            # index(*(1,2,3,4,5,6),**{"a":1,"b":2,"c":3})
                            # index(1,2,3,4,5,6,a=1,b=2,c=3)
wrapper(1,y=2,z=3)
# 1 2 3

了解(**):命名关键字形参: 在*与**中间的形参称之为命名关键字形参
特点: 必须按照key=value的形式传值

10.函数的基本使用

原文:https://www.cnblogs.com/gfeng/p/14203702.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!