初识函数

一、为什么要用函数,有什么特点

     为防止代码的沉余,就是在程序中不断地重复出现的同样功能的代码块,先定义一个实现同样功能的代码块(函数),定义好后可以无限次的调用,显得更简洁方便,可读性更强。

s1 = "hello world"
length = 0
for i in s1:
    length = length+1

print(length)

s2 = "hello eva"
length = 0
for i in s2:  #重复上述的代码块功能
    length = length+1 

print(length)

二、函数的定义和调用

函数的定义:格式: def 函数名():固定的结构

 
 1 def mylen():
 2      
 3 #函数的固定格式 def+函数名():先定义后使用,命名的规则和变量名一致,
 4      # 不能用关键字,最好见名知意,只要定义一次就可以任意调用
 5 
 6      s1='hello world'
 7      length=0
 8      for i in s1:
 9         length=length+1
10     print(length)
11          # return length
12          # str_lne=mylen()
13          # print('str_lne:%s' %str_lne)

函数的结构:

def 函数名(参数1,参数2,*args,默认参数,**kwargs):
        """注释:函数功能和参数说明"""
        函数体
        ……
        return 返回值

定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":"。

   def 是固定的,不能变,空格 为了将def关键字和函数名分开

   函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短,并能表达函数功能

注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性。  # ("""   """   '    '   ''    ''   )

调用:就是 函数名() 

三、函数的返回值:

return关键字的作用

    return 是一个关键字,在pycharm里,你会看到它变成蓝色了。你必须一字不差的把这个单词给背下来。

  这个词翻译过来就是“返回”,所以我们管写在return后面的值叫“返回值”

要研究返回值,我们还要知道返回值有几种情况:分别是没有返回值、返回一个值、返回多个值

  # 函数内要想返回给调用者值 必须用关键字return
"""
  不写return
  只写return
  写return None
  写return返回一个值
  写return返回多个值
"""

没有返回值,不写return

def mylen():
     """计算s1的长度"""
     s1 = "hello world"
     length = 0
     for i in s1:
         length = length+1
     print(length)
     #函数的调用
  str_len=mylen() #因为没有返回值,此时的str_len为None
 print('str_len : %s'%str_len)

二:返回一个值

 def ret_demo():
     print(111)
    return None
 print(2222)
kil=ret_demo()
print(kil)

返回的结果
>>2222
>>111
>>>None

  关于赋值与调用的关系:首先a和b 被赋值指向同一个内存地址,后a又被重新赋值后指向了另一块内存地址,而b任然不变

三、返回多个值:定义好的函数,被调用后,return什么数据类型就返回什么类型的值,多种类型的话会以   '' 元组''   的形式返回

 1  def func():
 2  return(1,3,4,5,67,68,67,45,3,2,)
 3     #可以return任何数据类型,多值被return的话默认以元组的形式返回,
 4  res=func()
 5  print(res)
 6  def func1():
 7      return{'user_name':'Gilen','age':18,'habby':'write'}
 8 def func2():
 9     return['day',12,'music','best','big',78]
10  print(func(),func1(),func2)

四、函数的参数:def mylen()  #括号内的数就叫参数,分为形参和实参之分,在函数定义前命名的叫形参,调用过程命名的叫实参

#函数定义
def mylen(s1):
    """计算s1的长度"""
    length = 0
    for i in s1:
        length = length+1
    return length

#函数调用
str_len = mylen("hello world")
print('str_len : %s'%str_len)

 实参与形参

参数还有分别:

我们调用函数时传递的这个“hello world”被称为实际参数,因为这个是实际的要交给函数的内容,简称实参。

定义函数时的s1,只是一个变量的名字,被称为形式参数,因为在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参

传递多个参数

参数可以传递多个,多个参数之间用逗号分割。def mylen(x, y)

1:位置参数: 在函数定义阶段按照位置从左往右依次书写的变量名 叫做函数位置形参
 位置形参在调用的时候 必须为其传值

def my_max(x,y):
    print(x,y)
    if x > y:
        return x
    else:
        return y
# res = my_max(1)  # 在调用函数的时候 少一个实参不行
# res = my_max(1,2,3)  # 在调用函数的时候 多一个实参也不行

# res = my_max(20,10)

# 位置实参:在函数的调用阶段 传入的参数会按照位置一一对应给形参
# print(res)

第一种直接按照位置传  一一对应

2.按照关键字传值

# 第二种指名道姓的传  >>>:关键字传参
# my_max(y=20,x=10)
# my_max(10,y=20)  # 位置和关键字混合使用
# my_max(20,y=40)
my_max(20,y=40,x=30)

 3.位置、关键字形式混着用

注意:在函数的调用阶段 位置参数和关键字参数可以混合使用

  但是必须保证
    1.位置参数必须在关键字参数的前面(越短的越靠前,越长的越复杂的越靠后)
    2.同一个形参不能被多次赋值

def mymax(x,y):
    #此时x = 10,y = 20
    print(x,y)
    the_max = x if x > y else y
    return the_max

#调用mymax不传递参数
ma = mymax()
print(ma)

#结果
TypeError: mymax() missing 2 required positional arguments: 'x' and 'y'

4、默认参数

    默认值参数:在函数的定义阶段,形参(变量名)就已经被赋值了

在调用的时候可以不为默认值形参的传值,默认使用定义阶段就已经被绑定的值

在调用的时候如果可以给默认值形参传值,传了那么久使用你传的值

在定义阶段 默认值形参必须放在位置形参的后面 。 

 def my_max(x,y=100):
    if x > y:
        return x
   return y res = my_max(200)
res1 = my_max(200,1000)
 res2 = my_max(y=200,x=1000)
 print(res2)

def register(username,age,gender='male'):
   print(username,age,gender)
register('jason',18)
register('tank',28)
register('egon',84)
register('kevin',58)  ##默认的认为gender为’ male ‘ 如果不是的话在赋值修改即可
register('xiaohou',17,'female')

  函数无论在什么地方被调用

都会跑到函数定义阶段去执行代码  

形参中用到的值都是往函数定义阶段代码往上找

5、动态参数:

  按位置传值多余的参数都由args统一接收,保存成一个元组的形式

形参中的*会将多余的(溢出的)位置实参 统一用元组的形式处理 传递给*后面的形参名

  站在形参的角度 看 *

def func(x,y,*z):
     print(x,y,z)  # z = (3, 4, 5, 6, 7, 8, 54, 43, 4, 5, 6, 6, 7, 8)
func(1,2,3,4,5,6,7,8,54,43,4,5,6,6,7,8,)

 x对应1,y对应2,溢出的部分赋值到z,且以元组的形式返回来

站在实参的角度 看 *

  

ef func(x,*z):
     print(x,z)
func(1,*{1,2,3})

# *在形参中只能接收多余的位置实参 不能接收关键字实参
# *只能将列表 元组 集合 字符串
# *的内部你可以看成是for循环

站在形参的角度看 **

  # **会接收所有多余的关键字参数 并将关键字参数 转换成字典的形式 字典的key就是关键字的名字
# 字典的value就是关键字的名字指向的值  将字典交给**后面的变量名

 # 站在实参的角度看 **

def func(x,y,z):
    print(x,y,z)
# func(12,3,4)
# func(x=1,y=2,z=3)
# d = {'x':1,'y':2,'z':333}
# func(x=1,y=2,z=3)
# func(**d)  # 等价于func(x=1,y=2,z=333)
# **会将字典拆封成 key = value的形式


总结 :* 与 **
    *在形参中能够接受多余的位置参数 组织成一个 元祖 赋值给*后面的变量名
    **在形参中能够接受多余的关键字参数 组织成一个 字典 赋值给**后面的变量名
   
   
    *:在实参中 *能够将列表 元祖 集合  字符串  打散成位置 实参  的形式传递给函数
        (*就看成是for循环取值)
    **:在实参中 能将字典打散成    key=vlaue    的形式 按照关键字参数传递给函数

注意python推荐形参*和**通用的写法

def func2(*args,**kwargs):
    print(args,kwargs)
func2(1,2,3,4,5,6,x=1,y=2,z = 3)

  

原文地址:https://www.cnblogs.com/Gaimo/p/11158595.html