语言基础之:函数

  • 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
  • 具有减少重复代码,使程序变的可扩展,易维护等特点

1 函数的定义规则

def new_function(x, y):  # 此处x,y为形参
    "The function definitions"
    x + y
    return x, y


def:定义函数的关键字
test:函数名
():"()"内定义形参
"":文档描述(建议为你的函数添加描述信息)
x + y:泛指代码块或程序处理逻辑
return:定义返回值

# 调用参数
new_function(1, 2)  # 此处1,2为实参    
  • 默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。

2 返回值return

  • 作用:后续程序可能需要根据返回值结果进行下一步操作
def func1():
    """定义过程函数,0个返回值"""
    print("定义过程函数,0个返回值")


def func2():
    """定义函数,1个返回值"""
    print("定义函数,1个返回值")
    return 0


def func3():
    """定义函数,多返回值"""
    print("定义函数,多返回值")
    return 1, 1.1, 'abc', ['a', 'b'], {'age': 1}, ('a', 'b'), func2, func2()
# 可以返回func2函数名称,返回的是函数内存地址,
# 可以返回func2()函数,返回的是func2()函数的返回值


x = func1()
y = func2()
z = func3()

print("定义过程函数,0个返回值:", x)
print("定义函数,1个返回值:", y)
print("定义函数,多返回值:", z)

总结

  • 返回值数=0:返回none
  • 返回值数=1:返回object
  • 返回值数>1:返回tuple(一个元组,return的多个值撞到一个元组中)

3 函数之间调用

  • 函数之间调用,需要被调用的函数在调用函数之前。
import time

def logger():
    """logger被调用函数"""
    time_format = "%Y-%m-%d %X"
    time_current = time.strftime(time_format)
    with open("testfile", "a") as f:
        f.write("\n%s add" % time_current)


def test1():
    """第一次调用"""
    print("this is test1")
    logger()


def test2():
    """第二次调用"""
    print("this is test2")
    logger()


test1()
test2()

4 形参与实参

形参:

  • 变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
    实参:
  • 可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

4.1 含参数的函数

def func1(x, y, z):
    print("x = ", x)
    print("y = ", y)
    print("z = ", z)


# 位置参数调用,与形参顺序一一对应
func1(1, 2, 3)
# 关键字调用,与形参顺序无关
func1(x=2, y=3, z=1)
# 关键字调用用位置参数调用同时存在,关键参数是不能写在位置参数前面的
func1(1, 2, z=3)
# func1(x=2, y=1, 3)
# SyntaxError: positional argument follows keyword argument
# func1(3, x=2, y=1)
# TypeError: func1() got multiple values for argument 'x'

4.2 *args

  • 接受N个位置参数,转换成元组形式
def func1(*args):
    print(args)


func1(1)
# 输出:(1,)
func1(1, 2, 3, 4)
# 输出:(1, 2, 3, 4)


# "*"表示args的参数不固定,可用其他变量名称替换,不建议
def func2(*x):
    print(x)


func2(*['a', 2, 'c'])
# 输出:('a', 2, 'c')


def func3(x, *args):
    print(x)
    print(*args)


func3(1, 2, 3, 4, 5)
# 输出:1
# 输出:2 3 4 5

4.3 **kwargs

  • 接受N个关键字参数,转换成字典的方式
def func1(**kwargs):
    print(kwargs)
    print(kwargs['语文'])
    print(kwargs['数学'])


func1(语文=100, 数学=90, 英语=80)
func1(**{'语文': 100, '数学': 90, '英语': 80})


def func2(name, **kwargs):
    print(name)
    print(kwargs)


func2('carey', age=200, sex='m')


# 参数组一定要放在最后
def func3(name, age=18, **kwargs):
    print(name)
    print(age)
    print(kwargs)


func3('carey', hobby='skateboard', age=200, sex='m')

4.4 多种实参,多种参数组

def func4(name, age=18, *args, **kwargs):
    print(name)
    print(age)
    print(args)
    print(kwargs)


func4('carey', 13, 'a', 'b', 'c', hobby='skateboard', sex='m')

5 局部变量与全局变量

name1 = 'carey'  # name1便是该函数的全局变量


def change_name(name):
    """change name"""
    print("before change:", name)
    name = "fan"  # 这个函数就是"name"的变量的作用域
    print("after change:", name)

    global name2  # 在函数内写全局变量,不要用!了解就好
    name2 = 'fan_carey2'
    print("global name2", name2)
    name3 = 'f_carey3'


change_name(name1)
# 输出:before change: carey
# after change: fan
# global name2 fan_carey2

print("函数之外的name1:", name1)
# 输出:函数之外的name1: carey
print("global name2:", name2)
# 输出:global name2: fan_carey2
print("函数之内的name3:", name3)
# 输出:NameError: name 'name3' is not defined
  • 列表在函数中修改变量后,全局也发生改变
# 列表在函数中修改变量后,全局也发生改变
# 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
# 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

list1 = ["a", "b", "c"]
def change_list():
    list1[0] = "abc"
    print("inside list1:", list1)

change_list()
print("outside list1: ", list1)

6 递归

  • 函数在内部调用自身本身,这个函数就是递归函数。
  • 必须有一个明确的结束条件
  • 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
  • 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
    python 中最大递归次数为999
def calc1(n):
    print(n)
    return calc1(n+1)

calc1(0)

** 实例**

def calc2(n):
    print(n)
    if int(n/2) > 0:
        return calc2(int(n/2))
    print("-->", n)
calc2(10)

7 函数、函数式编程、高阶函数

  • 面向对象:特点:类(class)
  • 面向过程:过程(def)
  • 函数式编程:函数(def)

7.1 函数和过程

# 定义函数
def func1():
    """定义函数"""
    print("this is function1. ")
    return 0


# 定义过程
def func2():
    """定义面向过程函数"""
    print("this is function2")


# 调用定义函数
x = func1()
# 调用定义过程
y = func2()

print("func1.return:%s\nfunc2.return:%s" % (x, y))

# 输出
# this is function1.
# this is function2
# func1.return:0
# func2.return:None

过程和函数都可以调用,过程就是没有返回值的函数。

7.2 函数式编程

  • 只要输入确定,输出也确定
    一、定义
    简单说,“函数式编程"是一种"编程范式”(programming paradigm),也就是如何编写程序的方法论。
    主要思想是把运算过程尽量写成一系列嵌套的函数调用。
实例:
  (1 + 2) * 3 - 4
传统的过程式编程,可能这样写:
  var a = 1 + 2;
  var b = a * 3;
  var c = b - 4;
函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:
  var result = subtract(multiply(add(1,2), 3), 4);
以上就是函数式编程,这段代码再演进以下,可以变成这样
add(1,2).multiply(3).subtract(4)
这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:
merge([1,2],[3,4]).sort().search("2")
因此,函数式编程的代码更容易理解。

7.3 高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
(1)把函数作为实参
(2)把函数作为返回值

def add(a, b, f):
    return f(a)+f(b)
res = add(-1, -2, abs)

print(res)
posted @ 2022-03-24 19:01  f_carey  阅读(11)  评论(0编辑  收藏  举报  来源