python - 内置对象 之 自定义函数

目录

一、自定义函数基础

1.定义一个函数

2.函数调用

3.参数传递

4.函数参数类型

二、函数变量作用域

1.理解变量作用域

2.全局变量与局部变量

 三、lambda匿名函数

1.lambda函数定义

2.lambda函数实例

3.lambda函数的特点和使用场景

 四、return返回特性

1.return返回元组列表字典

2.return跳出循环或终止执行下面语句


 

一、自定义函数基础

1.定义一个函数

  • # 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
  • # 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • # 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • # 函数内容以冒号起始,并且缩进。
  • # return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

 

2.函数调用

  • 函数名([形参值])
  • # 形参值指创建函数时要求传入的各个形参的值。注意,创建函数时有多少个形参,那么调用时就需要传入多少个值,且顺序必须和创建函数时一致。即便该函数没有参数,函数名后的小括号也不能省略。
  • 在定义函数时,函数名后面括号中的变量名称叫做形式参数,或者称为形参。
  • 在调用函数时,函数名后面括号中的变量名称叫做实际参数,或者称为实参。

 

3.参数传递

(1)不可变类型

  • # 如整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
#!/usr/bin/python

# -*- coding: UTF-8 -*-

def ChangeInt( a ):

    a = 10

    b = 2


ChangeInt(b)

print(b) # 结果是 2

 

(2)传可变对象实例

  • # 如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
(2)传可变对象实例
# 如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
def changeme( mylist ):
   "修改传入的列表"
   mylist.append([1,2,3,4]);
   print("函数内取值: ", mylist)
   return
 
# 调用changeme函数
mylist = [10,20,30];
changeme( mylist );
print("函数外取值: ", mylist)
# 函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
# 函数外取值:  [10, 20, 30, [1, 2, 3, 4]]

 

4.函数参数类型

# 必备参数 # 关键字参数 # 默认参数 # 不定长参数

(1)必备参数

# 必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。


def printme( str1,str2 ):
   "打印任何传入的字符串"
   print(str1,str2);
   return;
 
#调用printme函数
printme('john','harry');

(2)关键字参数

# 函数调用使用关键字参数来确定传入的参数值,使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

def printinfo( name, age ):
       "打印任何传入的字符串"
   print "Name: ", name;
   print "Age ", age;
   return;
 
#调用printinfo函数
printinfo( age=50, name="miki" );

(3)默认参数

# 调用函数时,默认参数的值如果没有传入,则被认为是默认值。下例会打印默认的age,如果age没有被传入:

def printinfo( name, age = 35 ):
       "打印任何传入的字符串"
   print "Name: ", name;
   print "Age ", age;
   return;
 
#调用printinfo函数
printinfo( age=50, name="miki" );
printinfo( name="miki" );

(4)不定长参数:*args 和 **kwargs

  • 元组参数,即 *args,参数格式化存储在一个元组中,长度没有限制,必须位于普通参数和默认参数之后。在函数调用时,*会以单个元素的形式解包一个元祖,使其成为独立的参数。
  • 字典参数,即 **kwargs,参数格式化存储在一个字典中,必须位于参数列表的最后面。**会以键/值对的形式解包一个字典,使其成为独立的关键字参数。
#*args例子
def printinfo( arg1, *vartuple ):
       "打印任何传入的参数"
   print "输出: "
   print arg1
   for var in vartuple:
      print var
   return;
 
# 调用printinfo 函数
printinfo( 10 );
printinfo( 70, 60, 50 );
# 输出:
# 10
# 输出:
# 70
# 60
# 50

#**kwargs例子
def print_values(**kwargs):
    for key, value in kwargs.items():
        print("The value of {} is {}".format(key, value))
 
print_values(my_name="Sammy", your_name="Casey")


def fun(name, age=1, *args, **kwargs):
    print('Hello', name, age, '年')  # Hello World 1 年
    print(args)  # ('I', 'love', 'it')
    for i in args:
        print(i)
    print(kwargs)  # {'my': 'jack', 'like': 'girl'}
    for m in kwargs:
        print(m, ':', kwargs[m])


fun('World', 1, 'I', 'love', 'it', my='jack', like='girl')
# 结果:
# Hello World 1 年
# ('I', 'love', 'it')
# I
# love
# it
# {'my': 'jack', 'like': 'girl'}
# my : jack
# like : girl

 

(5)关于**kwargs、位置参数、*args、默认参数混用问题:(注意顺序)

# 位置参数、*args、**kwargs三者的顺序必须是:位置参数、*args、**kwargs,否则会出错。
def func(x,*args,**kwargs):
        print('x = ',x)
    print('args = ',args)
    print('kwargs = ',kwargs)
 
func(1,2,3,4,y=1,a=2,b=3,c=4)
# 结果:
# x =  1
# args =  (2, 3, 4)
# kwargs =  {'b': 3, 'c': 4, 'a': 2, 'y': 1}

位置参数、默认参数、**kwargs的顺序必须为:位置参数、默认参数、**kwargs,否则会报错。

def func(x,y=2,**kwargs):
        print('x = ',x)
    print('y = ',y)
    print('kwargs = ',kwargs)
 
func(1,y=1,a=2,b=3,c=4) 
# 结果为:
x =  1
y =  1
kwargs =  {'c': 4, 'a': 2, 'b': 3}

 

二、函数变量作用域

1.理解变量作用域

(1)变量的作用域

  • 在Python程序中创建、改变、查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域。python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量能被访问的范围。即Python变量的作用域由变量所在源代码中的位置决定。

(2)作用域的产生

  • 就作用域而言,Python与C有着很大的区别,在Python中并不是所有的语句块中都会产生作用域。只有当变量在Module(模块)、Class(类)、def(函数)中定义的时候,才会有作用域的概念。
  • 需要注意的是:在if-elif-else、for-else、while、try-except\try-finally等关键字的语句块中并不会产成作用域。

(3)作用域的类型

  • # L (Local) 局部作用域
  • # E (Enclosing) 闭包函数外的函数中
  • # G (Global) 全局作用域
  • # B (Built-in) 内建作用域

(4)查找规则

  • # 以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
  • # 闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
x = int(2.9)  # 内建作用域B
g_count = 0  # 全局作用域G
def outer():
    o_count = 1  # 闭包函数外的函数中E
    def inner():
        i_count = 2  # 局部作用域L

 

2.全局变量与局部变量

  • # 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
  • # 当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字了。

(1)修改全局变量

num = 1
def fun1():
    global num  # 需要使用 global 关键字声明
    print(num) 
    num = 123
    print(num)
fun1()
print(num)

# >>>
# 1
# 123
# 123

(2)修改嵌套作用域中的变量

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print(num)
    inner()
    print(num)
outer()

# >>>
# 100
# 100

 

 三、lambda匿名函数

1.lambda函数定义

  • # python 使用 lambda 来创建匿名函数。lambda函数的语法只包含一个语句,如下:
  • lambda [arg1 [,arg2,.....argn]]:expression
  • # lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值。
  • # lambda匿名函数的格式:冒号前是参数,可以有多个,用逗号隔开,冒号右边的为表达式。其实lambda返回值是一个函数的地址,也就是函数对象。

 

2.lambda函数实例

s=lambda x,y:x+y

h=lambda x,y,z:x+y-z

print(s(10,20),h(10,20,50))

 

3.lambda函数的特点和使用场景

(1)特点

  • # 从函数命名的角度:匿名,直接返回可供调用的值
  • # 从输入输出的角度:支持多个输入参数,但只支持一个表达式
  • # 从函数功能的角度:结构简单,无须定义函数名。但所能实现的功能也极其受限。
  • # 从访问变量的角度:只支持访问lambda自己定义的变量。不支持外部变量访问
  • # 从运行效率的角度:lambda实际上仍开辟了一个内存单元,并没有提升运行效率

 

(2)使用场景

  • # lambda函数复制给变量:减少函数定义的麻烦,同时支持代码复用。
  • # lambda函数赋值给函数:利用lambda函数实现对已有函数的重新定义。
  • # 利用lambda函数进行函数嵌套:利用lambda构造嵌套的内部和外部函数,实现闭包编程
  • # 将lambda函数作为参数传递给其他函数

 

部分Python内置函数接收函数作为参数。典型的此类内置函数有这些。

filter函数

此时lambda函数用于指定过滤列表元素的条件。

filter(lambda x: x % 3 == 0, [1, 2, 3])

指定将列表[1,2,3]中能够被3整除的元素过滤出来,其结果是[3]。

sorted函数

此时lambda函数用于指定对列表中所有元素进行排序的准则。

sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))

将[1, 2, 3, 4, 5, 6, 7, 8, 9]按照与5距离从小到大进行排序,结果是[5, 4, 6, 3, 7, 2, 8, 1, 9]

map函数

此时lambda函数用于指定对列表中每一个元素的共同操作。

如map(lambda x: x+1, [1, 2,3])

将列表[1, 2, 3]中的元素分别加1,其结果[2, 3, 4]。

reduce函数

此时lambda函数用于指定列表中两两相邻元素的结合条件。

reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])

将[1, 2, 3, 4, 5, 6, 7, 8, 9]中元素从左往右两两以逗号分隔的字符的形式依次结合起来,其结果是'1, 2, 3, 4, 5, 6, 7, 8, 9'。

 

 四、return返回特性

1.return返回元组列表字典

(1)返回元组

def func():
    x=0
    y=1
    z=2
    return x,y  #返回元组

print(type(func()))

(2)返回列表

def func():
    x=0
    y=1
    z=2
    return [x,y]  #返回列表

print(type(func()))

(3)返回字典

def func():
    x=0
    y=1
    z=2
    return {x,y}  #返回字典

print(type(func()))

 

2.return跳出循环或终止执行下面语句

  • 执行到return语句时,会退出函数,return之后的语句不再执行,有循环也会跳出循环。但将return语句放在try语句块中,是个例外。

(1)普通情况:遇return退出函数,不执行return之后语句

def test_return(x):
    if x > 0:
        return x
    else:
        return 0

(2)有循环也出跳出循环

def test_return(x):
    for i in range(x):
        if i>=4:
            return i
        print(i)

test_return(10)
#结果:
#0
#1
#2
#3


def return_y(j):
    while j<10:
        print(j)
        j+=1
        if j==3:
            return 3
print(return_y(1))
#结果:
1
2
3      

(3)try..finally 结构中的return,遇到return后,还是会执行finally中的语句

def func():
    try:
        print(98)
        return 'ok'  # 函数得到了一个返回值
    finally:  # finally语句块中的语句依然会执行
        print(18)

print(func())  
#结果:
#98
#18
#ok

(4)try..finally 结构中各有一个return,最后返回的是finally中的return

def func():
    try:
        x=0
        y=1
        z=2
        return [x,y]  # 函数得到了一个返回值
    finally:  #finally语句块中的语句依然会执行
        print("last return")
        return {x,z}

print(func())
#结果:
#last return
#{0, 2}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值