Python——函数的参数

本文详细介绍了Python中函数的参数类型、参数传递机制、参数的使用方式以及如何进行参数解包。主要内容包括位置参数、关键字参数、默认参数、可变参数和组合参数的应用,同时解释了不可变对象与可变对象的区别以及对参数的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 形参和实参

形参:函数定义里的参数。

实参:调用函数时传入的参数。

>>> def welcome(param1,param2):
...     print(param1,', ',param2)
...
>>>
>>> welcome('Hello','World')
Hello ,  World

其中,param1 和 param2 是函数的形参,而在函数 welcome() 被调用时,传入的('Hello' 和 'Python')则是实参。

【注】

  • 在函数体内都是对形参进行操作,不能操作实参,即对实参做出更改。
  • 作为实参传入函数的变量名称和函数定义里形参的名字没有关系。

 

二. 参数传递

在 python 中,类型属于对象,变量是没有类型的:

a=[1,2,3]

a="zth"

以上代码中,[1,2,3] 是 List 类型,"zth" 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。

 

1. 可更改(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没有动,只是其内部的一部分值被修改了。

2. python 函数的参数传递:

  • 不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。

  • 可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响

 

python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

 

python 传不可变对象实例

>>> def  ChangeInt(a):
...     a = 10
...
>>> b =2
>>> b
2

实例中有 int 对象 2,指向它的变量是 b,在传递给 ChangeInt 函数时,按传值的方式复制了变量 b,a 和 b 都指向了同一个 Int 对象,在 a=10 时,则新生成一个 int 值对象 10,并让 a 指向它。

 

传可变对象实例

可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。

>>> def channgeme(mylist):
...     "修改传入的列表"
...     mylist.append([1,2,3,4])
...     print("函数内取值:",mylist)
...     return
...
>>>
>>> mylist = [7,8,9]

>>> channgeme(mylist)
函数内取值: [7, 8, 9, [1, 2, 3, 4]]


>>> print("函数外取值:",mylist)
函数外取值: [7, 8, 9, [1, 2, 3, 4]]
>>>

 

传入函数的和在末尾添加新内容的对象用的是同一个引用。

 

三. 参数

调用函数时可以使用以下参数类型:

  1. 位置参数
  2. 关键字参数
  3. 默认参数
  4. 可变参数
  5. 组合参数

1. 位置参数

位置参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

>>> def  printme( str):
...     print(str)
...     return
...
>>>
>>> printme("Hello World")              # 一个参数
Hello World
>>>
>>>
>>> printme()                           # 没有参数
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: printme() missing 1 required positional argument: 'str'
>>>
>>>
>>> printme("Hello" ," World")          # 多于一个参数
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: printme() takes 1 positional argument but 2 were given

 

2. 关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

>>> def personinfo(name,age):
...     print('姓名:',name)
...     print('年龄:',age)
...     return
...
>>>
>>> personinfo('zth',20)                        # 按参数顺序传入参数
姓名: zth
年龄: 20
>>>
>>>
>>> personinfo(name='zth',age=20)               # 按参数顺序传入参数,并指定参数名
姓名: zth
年龄: 20
>>>
>>>
>>> personinfo(age = 20, name = 'zth')          # 不按参数顺序传入参数,并指定参数名
姓名: zth
年龄: 20
>>>
>>>
>>> personinfo(20,'zth')                        # 不按参数顺序传入参数
姓名: 20
年龄: zth
>>>
>>>
>>> personinfo( name = 'zth')                   # 传入部分参数,并指定参数名
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: personinfo() missing 1 required positional argument: 'age'
>>>
>>>
>>> personinfo( 'zth')                          # 传入部分参数,不指定参数名
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: personinfo() missing 1 required positional argument: 'age'

【注】

关键字参数必须在位置参数之后,所有传递的关键字参数都必须与函数接受的某个参数匹配,并且它们的顺序不重要。

 

3. 默认参数

定义函数时,可以使用赋值运算符(=)为参数指定一个默认值。

调用函数时,如果没有传递参数,则会使用默认参数。

注意: 如果参数没有默认值,在调用时必需为其指定一个值;如果参数有默认值,那么在调用时值是可选的,如果为其提供了一个值,将会覆盖默认值。

>>> def personinfo(name,age=23):
...     print("姓名:",name)
...     print("年龄:",age)
...     return
...
>>>
>>>
>>> personinfo('zth')           # 还用默认age
姓名: zth
年龄: 23
>>>
>>> personinfo('zth',20)        # 传入 age 参数
姓名: zth
年龄: 20
>>>

默认参数一定要放在非默认参数后面:

>>> def personinfo(age=23,name):
...     print("姓名:",name)
...     print("年龄:",age)
...     return
...
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

 

  • 无论有多少默认参数,默认参数都不能在位置参数之前。
  • 无论有多少默认参数,若不传入默认参数值,则使用默认值。
  • 若要更改某一个默认参数值,又不想传入其他默认参数,且该默认参数的位置不是第一个,则可以通过参数名更改要更改默认参数值。
  • 若有一个默认参数通过传入参数名更改参数值,则其他想要更改的默认参数都需要传入参数名更改数值,否则报错。
  • 更改默认参数值时,传入默认参数的顺序不需要根据定义的函数中的默认参数的顺序传入,不过最好同时传入参数名,否则容易出现执行结果与预期不一致的情况。
>>> def personinfo(name,age=20,addr = 'xian'):
...     print("姓名:",name,"\t年龄:",age,"\t地址:",addr)
...     return
...
>>> personinfo('zth')                                   # 传入必须参数
姓名: zth      年龄: 20       地址: xian
>>>
>>>
>>>
>>> personinfo('zth',21)                                # 传入必须参数,更改第一个默认参数值
姓名: zth      年龄: 21       地址: xian
>>>
>>>
>>>
>>> personinfo('zth',21,'chengdu')                      # 传入必须参数,更改全部默认参数值
姓名: zth      年龄: 21       地址: chengdu
>>>
>>>
>>>
>>> personinfo('zth',addr='chengdu')                    # 传入必须参数,更改指定默认参数名的参数值
姓名: zth      年龄: 20       地址: chengdu
>>>
>>>
>>> personinfo('zth',addr='chengdu',age = 21)           # 传入必须参数,指定参数名并更改值
姓名: zth      年龄: 21       地址: chengdu
>>>
>>>
>>> personinfo('zth',21,addr='chengdu')                 # 传入必须参数,第一个默认参数不带参数名,第二个带
姓名: zth      年龄: 21       地址: chengdu
>>>
>>>
>>> personinfo('zth',age = 21,addr='chengdu')           # 传入必须参数,两个默认参数都带参数名
姓名: zth      年龄: 21       地址: chengdu
>>>
>>>
>>> personinfo('zth',age = 21,'chengdu')                # 传入必须参数,第一个默认参数带参数名,第二个不带
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument

【注】定义默认参数要牢记一点:默认参数必须指向不变对象

>>> def add_end( L = []):
...     L.append('zth')
...     return L
...
>>>
>>> #正常调用时,结果没有错误
...
>>>
>>> add_end([1,2,3])
[1, 2, 3, 'zth']
>>> add_end(['fbb',20])
['fbb', 20, 'zth']
>>>
>>>
>>> add_end()           # 使用默认参数调用,一开始没有错误
['zth']
>>> add_end()           # 再次调用将会出错
['zth', 'zth']
>>>
>>>
>>> # 修改,用None这个不变对象来实现
...
>>> def add_end( L = None):
...     if L is None:
...             L= []
...     L.append('zth')
...     return L
...
>>>
>>> add_end()
['zth']
>>> add_end()
['zth']

原因解释如下:

Python函数在定义的时候,默认参数  的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了  的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

 

为什么要设计strNone这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

 

4. 可变参数

可变参数也被称为不定长参数,顾名思义,就是传入的参数个数是可变的,可以是任意个(0、1、2 … N)。

要定义可变参数,仅需在参数名之前添加一个星号(*)。在函数内部,这些参数被包装为一个 tuple。

必须在函数定义中使用位置参数以及可变参数时,位置参数始终必须在可变参数之前。

语法格式:

def functionname([formal_args,] *var_args_tuple ):
   "函数_文档字符串"
   function_suite
   return [expression]

加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。

如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。

>>> def printinfo( arg1,*vartuple):
...     "打印传入的所有参数"
...     print(arg1)
...     for var in vartuple:
...             print(var)
...     return
...
>>>
>>>
>>> printinfo(10)               # 可变参数未指定参数
10
>>>
>>>
>>> printinfo(10,20,3,5)                # 可变参数指定多个参数
10
20
3
5

 

参数带两个星号 **基本语法如下:

def functionname([formal_args,] **var_args_dict ):
   "函数_文档字符串"
   function_suite
   return [expression]

加了两个星号 ** 的参数会以字典的形式导入。

>>> def printinfo( arg1,**vardict):
...     "打印传入的所有参数"
...     print(arg1)
...     print(vardict)
...     return
...
>>>
>>> printinfo(1,2,3,4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: printinfo() takes 1 positional argument but 4 were given
>>> printinfo(1, a=2,b=3)
1
{'a': 2, 'b': 3}

声明函数时,参数中星号 * 可以单独出现,例如:

如果单独出现星号 * 后的参数必须用关键字传入。

>>> def f(a,b,*,c):
...     return a+b+c
...
>>>
>>> f(1,2,3)            # 报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 3 were given
>>>
>>>
>>> f(1,2,c=3)          # 正常
6

 

5. 组合参数

在 Python 中定义函数可以用位置参数、关键字参数、默认值参数和可变关键字参数,这 4 种参数可以组合使用。

定义参数的顺序必须是:位置参数、默认参数、可变参数、命名关键字参数和关键字参数。

>>> def f1(a, b, c=0, *args, **kw):
...     print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
...
>>>
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>>
>>>
>>> def f2(a, b, c=0, *, d, **kw):
...     print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
...
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

 

四. 对参数进行解包

正如“可变参数”那样,也可在函数调用中使用 * 操作符。只不过在这种情况下,与在函数定义中 * 的语义相反,参数将被解包而不是打包。

>>> def greet(name, age):
...     print(name, age)
...
>>>
>>> person   = ('zth', 20)
>>>
>>> greet( *person)
zth 20

同样地,字典也可以用 ** 操作符传递关键字参数:

>>>
>>> def greet(name, age=18):
...     print(name, age)
...     return
...
>>> person ={'name':'zth', 'age':20}
>>>
>>>
>>> greet( **person)
zth 20

 

 

### Python `join()` 函数参数说明 `join()` 是字符串对象的方法,在调用时不需要导入额外的库。此方法接收一个单一参数,即要连接起来的可迭代对象(如列表、元组等),并返回一个新的由这些元素组成的字符串,其中各元素之间会插入调用该方法的对象作为分隔符[^1]。 对于传入的参数有如下要求: - 可迭代对象内的所有成员都应该是字符串类型;如果不是,则会发生 TypeError 错误。 - 如果给定的是空序列,则直接返回空字符串。 ### 使用方法 为了使用 `join()` 方法,应当先定义好想要使用的分隔符——这可以是一个空格、逗号或是任意其他字符甚至为空字符串。接着指定希望被拼接在一起的字符串集合即可。 ```python separator = "-" # 定义分隔符为短横线 words_list = ["hello", "world"] # 被连接的字符串列表 result_string = separator.join(words_list) # 应用 join() 进行连接操作 print(result_string) # 输出结果:"hello-world" ``` 当不提供显式的分隔符而直接对字符串调用 `.join(iterable)` 时,默认情况下不会有任何额外字符加入到最终形成的字符串之中[^4]。 ### 示例代码展示 下面给出几个具体的例子来进一步解释如何运用这个强大的工具: #### 基础案例:简单单词组合 ```python # 创建简单的字符串数组 word_array = [&#39;Python&#39;, &#39;is&#39;, &#39;awesome&#39;] # 使用单个空格作为间隔符进行链接 sentence = &#39; &#39;.join(word_array) print(sentence) # 结果将是:“Python is awesome” ``` #### 复杂情况:自定义分割标记 ```python # 设计更复杂的场景,比如创建路径名 path_parts = [&#39;home&#39;, &#39;user&#39;, &#39;documents&#39;, &#39;file.txt&#39;] full_path = &#39;/&#39;.join(path_parts) print(full_path) # 展现形式类似于 Unix 文件系统的绝对路径:"/home/user/documents/file.txt" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值