python入门技术教程之函数
n=1∑100n
这种抽象记法非常强大,因为我们看到 ∑ 就可以理解成求和,而不是还原成低级的加法运算。
而且,这种抽象记法是可扩展的,比如:
n=1∑100n2+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的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);
②是如何设置默认参数。
当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
使用默认参数有什么好处?最大的好处是能降低调用函数的难度。
举个例子,我们写个一年级小学生注册的函数,需要传入name和gender两个参数:
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 的缩写,约定俗成,非强制)。
核心用法示例(运维场景常用)
比如写一个批量执行命令的函数,允许传入任意关键字参数(如超时时间、编码格式):
关键特性
**kwargs必须放在函数参数列表的最后(后面不能再跟普通参数);- 只能接收 关键字参数(调用时必须用
key=value形式传入); - 可通过字典的
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(顺序不确定)
- 点赞
- 收藏
- 关注作者
评论(0)