You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

512 lines
12 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 函数的参数\n",
"\n",
"## 一、基础知识"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Python 没有函数重载"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def ff( x ): return x \n",
"def ff( x,y ): return x + y # 同名函数后面的遮挡前面函数\n",
"\n",
"ff(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 值传递和引用传递"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 值传递 :字符串、数字、元组 [ 不可变 ]\n",
"\n",
"def ff(x): x += 1 # 不改变调用值 a\n",
"a = 5 ; ff(a) ; a"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 引用传递: 列表、字典 [可变]\n",
"\n",
"def ff(x): x.append(1) # 改变调用值 a\n",
"a = [ 0 ] ; ff(a); a"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 二、函数参数形式\n",
"\n",
"Python函数的参数传递非常灵活支持多种参数形式使得函数定义和调用更加强大和灵活。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.1 普通参数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 位置参数\n",
"\n",
"位置参数是最基本的参数形式,按照它们在函数定义中的顺序传递。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello Alice, you are 25 years old\n"
]
}
],
"source": [
"def greet(name, age): # name 和 age 是位置参数\n",
" print(f\"Hello {name}, you are {age} years old\")\n",
"\n",
"# 调用方式\n",
"greet(\"Alice\", 25) # 参数按照定义的顺序传入,\"Alice\" 对应 name30 对应 age"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 默认参数\n",
"\n",
"为某些参数设置默认值,如果调用时不提供该参数,则使用默认值。"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello, Bob. You are 18 years old.\n",
"Hello, Charlie. You are 25 years old.\n"
]
}
],
"source": [
"def greet(name, age=18):\n",
" print(f\"Hello, {name}. You are {age} years old.\")\n",
"\n",
"greet(\"Bob\") # 使用默认年龄\n",
"greet(\"Charlie\", 25) # 提供具体年龄"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 调用函数时指定参数名\n",
"\n",
"通过参数名进行传递,参数顺序可以任意调整,提高了代码的可读性。"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Charlie 20\n",
"Charlie 20\n",
"Charlie 20\n",
"Charlie 20\n"
]
}
],
"source": [
"def greet( name,age ): print( name,age) \n",
"\n",
"greet( name = 'Charlie', age=20 ) # 命名传递参数,更清楚\n",
"greet( age = 20,name = 'Charlie' ) # 顺序可以改变\n",
"greet( 'Charlie',age = 20 ) # 混合使用,普通调用放前面,命名调用放后面\n",
"\n",
"name,age = 'Charlie',20 \n",
"greet( name = name, age = age ) # 形参、实参数同名的情况"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.2 可变参数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 可变位置参数 \n",
"- 使用星号(*)定义可变数量的位置参数,这些参数被存储在一个元组中。"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6\n",
"15\n"
]
}
],
"source": [
"def sum_numbers(*args):\n",
" return sum(args)\n",
"\n",
"# 调用方式\n",
"print(sum_numbers(1, 2, 3)) # 输出: 6\n",
"print(sum_numbers(1, 2, 3, 4, 5)) # 输出: 15"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 关键字参数(命名参数、字典参数)\n",
"\n",
"- 放在可变位置参数后面 \n",
"- 调用的时候,必须使用名字赋值形式"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1, (2, 3), 2)"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def ff(a,*b,c): return a,b,c\n",
"\n",
"ff( 1,c = 2 ) \n",
"ff( 1,2,c = 2 )\n",
"ff( 1,2,3,c = 2 ) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 没有可变参数,也要用 * 占位\n",
"\n",
"def ff(a,*,b): return a,b\n",
"ff(1,b=2)"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 () 0\n",
"1 2\n",
"1 3\n"
]
},
{
"data": {
"text/plain": [
"(None, None)"
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 有默认值的情况\n",
"\n",
"def ff( a,*b,c = 0 ): print(a,b,c) \n",
"ff(1)\n",
"\n",
"def ff( a = 1,*, b = 2 ): print(a,b) \n",
"ff(),ff( b = 3 ) # 前面是带默认值的位置参数"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello Alice, you are 25 years old\n"
]
}
],
"source": [
"# 函数以空*开头,强制函数用关键字参数,可提升代码可读性\n",
"\n",
"def greet(*, name, age): # * 之后的参数只能用关键字参数\n",
" print(f\"Hello {name}, you are {age} years old\")\n",
"\n",
"# 正确调用\n",
"greet(name=\"Alice\", age=25)\n",
"\n",
"# 错误调用\n",
"# greet(\"Alice\", 25) # 无 关键字命名 错误"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 可变关键字参数\n",
"\n",
"使用两个星号(**)定义可变数量的关键字参数。这些参数被存储在一个字典中。"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"name: Eve\n",
"age: 28\n",
"city: London\n"
]
}
],
"source": [
"def print_info(**kwargs):\n",
" for key, value in kwargs.items():\n",
" print(f\"{key}: {value}\")\n",
"\n",
"# 调用方式\n",
"print_info( name=\"Eve\", age=28, city=\"London\" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 解包可变参数\n",
"\n",
"在函数调用时,可以使用星号(*)或两个星号(**)来解包列表、元组或字典,将其中的元素或键值对作为参数传递给函数。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def func(a, b, *args, **kwargs):\n",
" print(a, b, args)\n",
" for key, value in kwargs.items():\n",
" print(key, value)\n",
"\n",
"args = (3, 4) # 或者 [\"Alice\", 25, \"Beijing\"] 其它序列容器\n",
"kwargs = {'x': 5, 'y': 6} \n",
"func(1, 2, *args, **kwargs) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.3 混合使用各种参数"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 () 2 {}\n",
"1 () 2 {'d': 3}\n",
"1 () 2 {'d': 3, 'e': 4}\n",
"1 () 2 {'d': 3, 'e': 4}\n",
"1 () 2 {'d': 3, 'e': 4}\n"
]
}
],
"source": [
"# 顺序:普通参数、可变位置参数、命名参数、可变关键字参数\n",
"# 可变位置参数后面,命名参数选取剩下的就是可变关键字参数\n",
"\n",
"def ff( a,*b,c,**d ): print( a,b,c,d )\n",
"\n",
"ff( 1,c=2 )\n",
"ff( 1,c=2,d=3 )\n",
"ff( 1,c=2,d=3,e=4 )\n",
"ff( 1,d=3,e=4,c=2 )\n",
"ff( 1,d=3,c=2,e=4 ) # 可推测其参数确定机制"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"普通参数 name : 1\n",
"普通参数 age : 2\n",
"可变参数 args : (3,)\n",
"命名参数 department : math\n",
"字典参数 kwargs : {}\n"
]
}
],
"source": [
"def ff( name , age ='20', *args, department = 'cs', **kwargs ): \n",
" '''\n",
" name 是必需的位置参数。\n",
" age 是带有默认值的位置参数。\n",
" *args 收集额外的位置参数。\n",
" **kwargs 收集额外的关键字参数。\n",
" ''' \n",
" print('普通参数 name :', name )\n",
" print('普通参数 age :', age )\n",
" print('可变参数 args :', args )\n",
" print('命名参数 department :', department )\n",
" print('字典参数 kwargs :', kwargs )\n",
"\n",
"# ff()\n",
"# ff(1)\n",
"# ff(1,2)\n",
"# ff(1,2,3)\n",
"# ff(1,2,3,4)\n",
"# ff(1,2,3,department='math')\n",
"# ff(1,2,3,u1='math')\n",
"# ff(1,2,3,4,5,u1='tsg',department='cmu',u2='pku' )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 基础代码中常用( *args,**kwargs )参数表来抽象表示一般函数的参数\n",
"\n",
"def ff( *args,**kwargs ): \n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 总结\n",
"\n",
"#### 参数顺序规则\n",
"<code>\n",
"def function(\n",
" 位置参数, # 普通参数\n",
" 默认参数 = '默认值', # 默认参数\n",
" *args, # 可变位置参数 \n",
" 关键字参数, # 普通关键字参数\n",
" **kwargs # 可变关键字参数\n",
"): pass\n",
"</code> \n",
"\n",
"- 可以有默认值:普通位置参数、 关键字参数"
]
}
],
"metadata": {
"hide_input": false,
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}