python入门技术教程之函数

举报
tea_year 发表于 2025/11/17 16:04:39 2025/11/17
【摘要】 n=1∑100n这种抽象记法非常强大,因为我们看到 ∑ 就可以理解成求和,而不是还原成低级的加法运算。而且,这种抽象记法是可扩展的,比如:n=1∑100n2+1还原成加法运算就变成了:(1 x 1 + 1) + (2 x 2 + 1) + (3 x 3 + 1) + ... + (100 x 100 + 1)可见,借助抽象,我们才能不关心底层的具体计算过程,而直接在更高的层次上思考问题。写计...

n=1100n

这种抽象记法非常强大,因为我们看到 ∑ 就可以理解成求和,而不是还原成低级的加法运算。

而且,这种抽象记法是可扩展的,比如:

n=1100n2+1

还原成加法运算就变成了:

(1 x 1 + 1) + (2 x 2 + 1) + (3 x 3 + 1) + ... + (100 x 100 + 1)

可见,借助抽象,我们才能不关心底层的具体计算过程,而直接在更高的层次上思考问题。

写计算机程序也是一样,函数就是最基本的一种代码抽象的方式,为了更好的复用代码。

函数的思路:就是封装重复代码,封装特定意义的代码.

函数调用

int():将字符串、浮点型数字转换成整型。

input():输入型的函数,可以加输入时候的提示信息,返回类型是字符串.

绝对值的函数abs

max():求n个数中的最大值

min():求nn个数中的最小值

float():将字符串 整形数字转换成浮点类型的函数

str(100):其他类型转换成字符串

bool(): 0 空 None都是False,其他都是True

函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:空是什么?

print(bool(0))      # False
print(bool(100))    # True
print(bool(''))     # False
print(bool(' '))    # True(空格不是空)
print(bool([]))     # False
print(bool([0]))    # True(列表非空)
print(bool(None))   # False

练习

请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串:

>>> hex(15)
'0xf'
>>> hex(16)
'0x10'			#0x:是16进制,开头的这种写法!
>>> hex(1)
'0x1'

普通函数

1.1 函数的定义与调用

定义:define

def 函数名(参数):
    函数体
    return 返回值

函数通过def关键字定义,def关键字后面跟着函数的函数名,函数名后面跟着小括号,小括号里面传入函数需要的参数(函数可以有参数也可以没有参数)。中间写函数体,最后写返回值(返回值可以有可以没有,默认为None)。

空函数

如果想定义一个什么事也不做的空函数,可以用pass语句:

def nop():					#无参数的函数
    pass

pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

函数定义并不会执行函数体内容, 必须要调用才会执行, 调用几次就会执行几次

函数必须先定义, 再使用.

函数参数

在函数定义的时候, 可以在 ( ) 中指定 "形式参数" (简称 形参), 然后在调用的时候, 由调用者把 "实际参数"(简称 实参) 传递进去.

这样就可以做到一份函数, 针对不同的数据进行计算处理.

考虑前面的代码案例:

 def calcSum(beg, end):
    sum = 0
    #beg=1,end=100
    #for i in range(1,101)
    for i in range(beg, end + 1):			#包左不包右,[beg,end+1)==>[beg,end]
        sum += i
    print(sum) 
# 调用函数
calcSum(1, 100)
calcSum(300, 400)
calcSum(1, 1000)

【说明】

上面的代码中, beg, end 就是函数的形参. 1, 100 / 300, 400 就是函数的实参;

在执行 sum(1, 100) 的时候, 就相当于 beg = 1, end = 100 , 然后在函数内部就可以针对 1-100 进行运算.

在执行 sum(300, 400) 的时候, 就相当于 beg = 300, end = 400 , 然后在函数内部就可以针对300-400 进行运算.

实参和形参之间的关系, 就像签合同一样

注意:

①一个函数可以有一个形参, 也可以有多个形参, 也可以没有形参.

②一个函数的形参有几个, 那么传递实参的时候也得传几个:保证个数要匹配.

③和 C++ / Java 不同, Python 是动态类型的编程语言, 函数的形参不必指定参数类型.

默认参数

由于我们经常计算x2,所以,完全可以把第二个参数n的默认值设定为2:

def power(x, n=2):			#5
    s = 1					#s=乘积
    while n > 0:			#n>0,执行;当n=0,退出;1>0
        n = n - 1			#2-1=1;	n=1-1=0;
        s = s * x			#s=1*5=5; s=5*5=25
    print(s)

这样,当我们调用power(5)时,相当于调用power(5, 2)

>>> power(5)
25
>>> power(5, 2)
25

而对于n > 2的其他情况,就必须明确地传入n,比如power(5, 3)

从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,有几点要注意

①是必选参数在前,默认参数在后,否则Python的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);

②是如何设置默认参数。

当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数

使用默认参数有什么好处?最大的好处是能降低调用函数的难度

举个例子,我们写个一年级小学生注册的函数,需要传入namegender两个参数:

def enroll(name, gender):
    print('name:', name)
    print('gender:', gender)

这样,调用enroll()函数只需要传入两个参数:

>>> enroll('Sarah', 'F')
name: Sarah
gender: F

如果要继续传入年龄、城市等信息怎么办?这样会使得调用函数的复杂度大大增加。

我们可以把年龄和城市设为默认参数:

def enroll(name, gender, age=6, city='郑州'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)

这样,大多数学生注册时不需要提供年龄和城市,只提供必须的两个参数:

>>> enroll('Sarah', 'F')
name: Sarah
gender: F
age: 6
city: Beijing

只有与默认参数不符的学生才需要提供额外的信息:

enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')

可见,默认参数降低了函数调用的难度,而一旦需要更复杂的调用时,又可以传递更多的参数来实现。无论是简单调用还是复杂调用,函数只需要定义一个。


可变参数

在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。

我们以数学题为例子,给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……。

要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:

def calc(numbers):			#a
    sum = 0
    for n in numbers:
        sum = sum + n * n			#sum+a*a
    print(sum)

但是调用的时候,需要先组装出一个list或tuple:

#list
>>> calc([1, 2, 3])
14
#tuple方式
>>> calc((1, 3, 5, 7))
84

如果利用可变参数,调用函数的方式可以简化成这样:

>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84

所以,我们把函数的参数改为可变参数:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:

>>> calc(1, 2)
5
>>> calc()
0

如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:

>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14

这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*,把list或tuple的元素变成可变参数传进去

>>> nums = [1, 2, 3]
>>> calc(*nums)
14

*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

关键字参数*

在 Python 中,** 是用于 关键字参数(Keyword Arguments) 的特殊语法,核心作用是 打包 / 解包字典形式的关键字参数,主要有两个核心使用场景:函数定义时接收任意关键字参数函数调用时解包字典作为关键字参数。

一、场景 1:函数定义时用 **kwargs 接收任意关键字参数

当函数定义时参数前加 **,表示该参数会接收 所有未显式定义的关键字参数,并将其打包成一个字典(dict),通常命名为 kwargs(Keyword Arguments 的缩写,约定俗成,非强制)。

核心用法示例(运维场景常用)

比如写一个批量执行命令的函数,允许传入任意关键字参数(如超时时间、编码格式)

关键特性

  1. **kwargs 必须放在函数参数列表的最后(后面不能再跟普通参数);
  2. 只能接收 关键字参数(调用时必须用 key=value 形式传入);
  3. 可通过字典的 get() 方法获取参数,避免未传参时的 KeyError

运维实战场景(结合 subprocess

import subprocess

def safe_ping(ip, **kwargs):
    """安全 ping 函数,支持传入 timeout、count 等关键字参数"""
    # 提取参数,设置默认值
    count = kwargs.get("count", 1)  # 默认发送 1 个包
    timeout = kwargs.get("timeout", 3)  # 默认超时 3 秒
    system = kwargs.get("system", "Windows")  # 默认 Windows 系统
    
    # 构造命令(适配 Windows/Linux)
    if system == "Windows":
        cmd = ["ping", "-n", str(count), "-w", str(timeout*1000), ip]
    else:
        cmd = ["ping", "-c", str(count), "-W", str(timeout), ip]
    
    # 执行命令
    result = subprocess.run(cmd, stdout=subprocess.PIPE, encoding=kwargs.get("encoding", "gbk"))
    return result.returncode == 0

# 调用:传入多个关键字参数
print(safe_ping("10.0.0.1", count=2, timeout=5, system="Windows"))
print(safe_ping("192.168.1.1", count=3, timeout=2, system="Linux", encoding="utf-8"))

函数返回值

函数的参数可以视为是函数的 " 输入 ", 则函数的返回值 , 就可以视为是函数的 " 输出 " .

此处的 "输入", "输出" 是更广义的输入输出, 不是单纯指通过控制台输入输出.

我们可以把函数想象成一个 "工厂". 工厂需要买入原材料, 进行加工, 并生产出产品.

函数的参数就是原材料, 函数的返回值就是生产出的产品.

我们可以看下列代码:

def calcSum(begin ,end):
    sum = 0
    for i in range (begin ,end+1):
        sum += i
    print(sum) 
    
calcSum(1,100)

这段代码是一个计算从begin到end之间所有整数的和的函数。它使用一个for循环来遍历从begin到end之间的整数,并将它们累加到变量sum中。最后,通过print函数打印出累加结果。

在这个例子中,调用calcSum(1, 100)会计算从1到100的所有整数的和,并将结果打印出来。

上述代码可以转换成 下述这样:

def calcSum(begin ,end):
    sum = 0
    for i in range (begin ,end+1):
        sum += i
    return sum 
result = calcSum(1,100)
print(result)

这两个代码的区别就在于 , 前者直接在函数内部进行了打印, 后者则使用 return 语句把结果返回给函数调用者, 再由调用者负责打印

我们一般倾向于第二种写法.

实际开发中我们的一个通常的编程原则, 是 "逻辑和用户交互分离". 而第一种写法的函数中, 既包含 了计算逻辑, 又包含了和用户交互(打印到控制台上). 这种写法是不太好的, 如果后续我们需要的是把计算结果保存到文件中, 或者通过网络发送, 或者展示到图形化界面里, 那么第一种写法的函数,就难以胜任了。

而第二种写法则专注于做计算逻辑, 不负责和用户交互. 那么就很容易把这个逻辑搭配不同的用户交互代码, 来实现不同的效果.

接下来,我在举几个例子带大家去瞧瞧:

一个函数中可以有多个 return 语句:

# 判定是否是奇数
def isOdd(num):
    if num % 2 ==0:
        return False
    else:
        return True 
result = isOdd(10)
print(result)

执行到 return 语句, 函数就会立即执行结束, 回到调用位置:

# 判定是否是奇数
def isOdd(num):
    if num % 2 ==0:
        return False
    return True 
result = isOdd(19)
print(result)

【解释说明】

如果 num 是偶数, 则进入 if 之后, 就会触发 return False , 也就不会继续执行 return True


一个函数是可以一次返回多个返回值的. 使用 , 来分割多个返回值

def getpoint():
    x=10
    y=20
    return x, y 
a ,b = getpoint()

如果只想关注其中的部分返回值, 可以使用 _ 来忽略不想要的返回值.

def getPoint():
    x = 10
    y = 20
    return x, y
_, b = getPoint()

*注意:空函数返回值测试是None

x=nop()
print(x)            #空函数的返回是None

函数名的应用

扩展:

函数在调用的时候,如何使用

函数名()的方式调用

4.1 函数名可以作为另一个函数的参数或者返回值

示例:函数名本质上是指向函数对象的引用,可以作为参数传递给其他函数,也可以作为函数的返回值返回。

def greet():
    # return 'hello'
    print("hello")

#再定义一个函数
def call_greet(func):
    func()              #调用函数,函数名()
    print(func)         #打印的是调用的函数的地址;

#调用一下,函数名greet,指的就是上面函数的地址;
call_greet(greet)


4.2 函数名可以成为字典、集合、列表、元组中的元素

示例:函数名作为函数对象,可以存储在各种数据结构中,便于动态调用。

def add(x, y):
    return x + y
 
def multiply(x, y):
    return x * y
 #定义了list列表,[函数名add,函数名multiply]
func_list = [add, multiply]

print(func_list[0](2, 3))  # 输出:5
#add(2,3)


print(func_list[1](2, 3))  # 输出:6



func_dict = {'加法': add, '乘法': multiply}
print(func_dict['加法'](4, 5))  # 输出:9
 
func_tuple = (add, multiply)
print(func_tuple[1](3, 7))  # 输出:21
 #字典
func_set = {add, multiply}
for f in func_set:
    print(f(1, 2))  # 依次输出3和2(顺序不确定)


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。