函数是组织好的,可重复使用的,用来实现单一,或相关关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。众所周知python提供了许多内置函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
你可以定义一个由自己想要功能的函数,以下是简单的规则:
函数代码块以def关键词开头,后接函数标识符名称和圆括号()
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
函数的第一行语句可以选择性地使用文档字符串-用于存放函数说明
def fun():""" :param _type: :param text: :param log_file_name: :return: """return None
函数内容以冒号起始,并且缩进
return[表达式]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None
python定义函数使用def关键字,一般格式如下:
def 函数名(参数列表):函数体
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
实例
让我们使用函数来输出“Hello World!”:
def hello():print("hello world!")hello()
更复杂点的应用,函数中带上参数变量:
#!/usr/bin/python3# 计算面积函数def area(width, height):return width*heightdef print_welcome(name):print("Welcome", name)print_welcome("Nowcoder")w = 4h = 5print("width =", w, " height =", h, " area =", area(w, h))
定义一个函数:给了函数一个名称,指定了函数里包含的参数和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从python命令提示符执行。
#!/usr/bin/python3# 定义函数def printme( str ):# 打印任何传入的字符串print (str)return# 调用函数printme("我要调用用户自定义函数!")printme("再次调用同一函数")
在 python 中,类型属于对象,变量是没有类型的:
a=[1,2,3]a="Nowcoder"
以上代码中,[1,2,3] 是 List 类型,"Nowcoder" 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。
可更改(mutable)与不可更改(immutable)对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
#!/usr/bin/python3def ChangeInt( a ):a = 10b = 2print(ChangeInt(b)) # 结果是10print( b ) # 结果是 2
实例中有 int 对象 2,指向它的变量是 b,在传递给 ChangeInt 函数时,按传值的方式复制了变量 b,a 和 b 都指向了同一个 Int 对象,在 a=10 时,则新生成一个 int 值对象 10,并让 a 指向它。
可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
#!/usr/bin/python3# 可写函数说明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]]
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
必需参数须以正确的顺序传入函数。调用时的数量必须和定义时的数量一样。
调用 printme() 函数,你必须传入一个参数,不然会出现语法错误:
#!/usr/bin/python3#可写函数说明def printme( str ):"打印任何传入的字符串"print (str)return# 调用 printme 函数,不加参数会报错printme()
调用函数时,关键字参数的使用不需要使用指定顺序:
#!/usr/bin/python3#可写函数说明def printinfo( name, age ):"打印任何传入的字符串"print ("名字: ", name)print ("年龄: ", age)return#调用printinfo函数printinfo( age=50, name="nowcoder" )
调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:
#!/usr/bin/python3#可写函数说明def printinfo( name, age = 35 ):"打印任何传入的字符串"print ("名字: ", name)print ("年龄: ", age)return#调用printinfo函数printinfo( age=50, name="nowcoder" )print ("------------------------")printinfo( name="nowcoder" )
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下:
def functionname([formal_args,] *var_args_tuple):"""函数_文档字符串"""function_suitereturn [expression]
加了星号*的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
# !/usr/bin/python3# 可写函数说明def printinfo(arg1,*vartuple):"打印任何传入的参数"print("输出:")print (arg1)print (vartuple)# 调用printinfo 函数printinfo( 70, 60, 50 )# 输出70(60,50)
如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。如下实例:
#!/usr/bin/python3# 可写函数说明def printinfo( arg1, *vartuple ):"打印任何传入的参数"print ("输出: ")print (arg1)for var in vartuple:print (var)return# 调用printinfo 函数printinfo( 10 )printinfo( 70, 60, 50 )# 输出10# 输出706050
参数带两个星号,基本语法如下:
def functionname([formal_args,] **var_args_dict):"函数_文档字符串"function_suitereturn [expression]
加了两个星号的参数会以字典的形式导入,以关键字。
#!/usr/bin/python3# 可写函数说明def printinfo( arg1, **vardict ):"打印任何传入的参数"print ("输出: ")print (arg1)print (vardict)# 调用printinfo 函数printinfo(1, a=2,b=3)# 输出1{'a': 2,'b':3}
声明函数时,参数中星号*可以单独出现,例如:
def f(a,b,*,c):return a+b+c
星号*后的参数必须用关键字传入。
>>>def f(a,b,*,c):... returna+b+c... >>>f(1,2,3) # 报错Traceback (mostrecentcalllast):File"<stdin>", line1, in<module>TypeError: f() takes2positionalargumentsbut3weregiven>>>f(1,2,c=3) # 正常6
python使用lambda来创建匿名函数。
所谓匿名,即不再使用def语句这样标准的形式定义一个函数。
lambda只是一个表达式,函数体比def简单很多
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去
lambda函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数
虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,C或C++的目的是调用小函数时不占用栈内存从而增加运行效率
语法:
lambda [arg1 [,arg2...]]:expression如下实例:
#!/usr/bin/python3# 可写函数说明sum = lambda arg1, arg2: arg1+arg2# 调用sum函数print ("相加后的值为 : ", sum( 10, 20 ))print ("相加后的值为 : ", sum( 20, 20 ))
在python中,可以在一个函数内部定义另一个函数。这种嵌套函数的定义方式在某些情况下非常有用,例如实现闭包、装饰器或隐藏内部实现细节。
基本语法
def outer_function():# 外部函数def inner_function():# 内部函数print("这是内部函数")inner_function()print("这是外部函数")# 调用外部函数outer_function()
闭包是一种可以记住并访问其创建时作用域链中的变量的函数,即使该函数在其创建上下文之外执行。
def outer_function(x):def inner_function(y):return x+yreturn inner_function# 创建闭包closure = outer_function(10)# 调用闭包result = closure(5)print(result) # 输出: 15
装饰器是 Python 中一种常用的模式,用于在不修改函数代码的情况下扩展函数的功能。
def my_decorator(func):def wrapper():print("在函数执行之前")func()print("在函数执行之后")return wrapper@my_decoratordef say_hello():print("Hello!这是扩展功能")say_hello()
作用域:
内部函数可以访问外部函数的变量,但外部函数不能访问内部函数的变量。
内部函数的作用域是局部的,只在外部函数内部有效。
闭包:
如果内部函数引用了外部函数的变量,即使外部函数已经执行完毕,内部函数仍然可以访问这些变量。
性能:
嵌套函数可能会增加代码的复杂性,但通常不会对性能产生显著影响。
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None