函数参数(例如在Python中)

0 投票
8 回答
14095 浏览
提问于 2025-04-16 23:44

[函数]的参数是什么?它们有什么用?
我最近刚开始学习Python;我对编程还很陌生,抱歉问这个基础问题。

在我看的每一个Python教程中,他们都会提到参数。我查找过这个问题的答案,发现了很多答案,但对我来说有点难以理解。可能是我缺少一些基本概念的背景知识。
那么……当我定义一个函数时,括号里的东西是用来干什么的呢?举个例子:

def hi( This is the part that i dont get):
     print 'hi'

补充:
与这个问题相关的两个后续问题后来被关闭并合并到这里,因此一些答案可能有点不在上下文中。
这些后续问题是:[意译]

8 个回答

5

在这种情况下,使用参数只是一个演示,告诉你怎么用它们,可能不是最有效的方式,就像你展示的那样。函数非常有用。比如说,如果我想加两个数字:

def add(num1, num2):
  x = num1 + num2
  return x
add(1,3)

函数适合用来做重复的事情。比如说,在你的例子中,如果你需要对成百上千个名字说“你好”,你就不需要每次都用 raw_input() 函数去读取名字并加上一些文字,而是可以直接调用一个函数来完成这个任务,并把名字作为参数传给它。

关于你第二个问题,参数就是传给函数的变量。也就是说,无论你从外部传给它什么变量,比如我把数字1和3传给我的函数 add,在这个函数内部,它们就被称作 num1 num2

在你传递太多参数的情况下,会出现这样的情况:

>>> add(1,2)
3
>>> add(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes exactly 2 arguments (3 given)
>>> 

祝你好运!如果你需要进一步的帮助,随时可以给我发邮件 (sbrichards (at) mit.edu)

6

这不是一个关于Python的问题,而是一个通用的编程问题,非常基础。


在回答关于参数的问题之前,考虑到你问的其他问题,先来聊聊变量的概念
变量就是一个有名字的内存空间,可以用来存储程序需要的信息,并且可以随时取出来。换句话说,变量是程序员给出的一个符号名字,和它里面的内容相关联。程序员可以通过一些叫做赋值的操作来读取或写入变量的内容。
需要注意的是,变量的值(也就是内容)在程序编写时并不需要定义。只有在程序运行时才需要。这让程序可以在不知道具体值的情况下,描述对这些符号元素要执行的操作。比如,看看下面这段代码,它是一个更大程序的一部分:

# ... some logic above
ball_volume = 4.0 / 3 * math.pi * ball_radius
if ball_volume > 200:
   print ("Man, that's a big ball")
# ... more logic below

在写程序时,不需要知道ball_radius的实际值;但假设这个变量会包含某个假设的球的数值,这段代码就能描述如何计算这个球的体积。这样,当程序运行时,某种方式(稍后会详细说明)初始化了ball_radius变量,给它赋了一个合适的值,ball_volume变量也可以被初始化并使用,比如在条件语句(if)中,可能在下面的地方也会用到。 (在某个时刻,变量可能会超出作用域,但这个控制变量何时可以被程序访问的概念超出了这篇入门的范围)。
在某些编程语言中,特定变量可以关联的数据类型需要明确地定义,并且不能改变。例如,有些变量只能存储整数值,其他变量只能存储字符串(文本)值等等。而在Python中没有这样的限制,变量可以被赋值和重新赋值为任何类型的数据,但当然,程序员需要注意这一点,比如避免将文本数据传递给数学函数。

存储在变量中的数据可以来自非常不同的来源。许多教程和入门文档中的例子都是从键盘输入获取数据(就像你提到的raw_input)。这是因为它允许尝试这些教程片段的人进行交互式测试。但如果变量的数据只能来自用户的交互输入,程序的实用性就会受到限制。还有很多其他的数据来源,这就是编程如此强大的原因:变量可以用来自以下数据:

  • 数据库
  • 文本文件或各种文本格式的文件(XML, JSON, CSV等)
  • 各种格式的二进制文件
  • 互联网连接
  • 物理设备:摄像头、温度传感器等...

简而言之,参数,也叫做参数,是传递给函数的变量,通常用于提供函数不同的输出和行为。例如:

>>> def say_hello(my_name):
...    print("Hello,", my_name, "!")

>>> say_hello("Sam")
Hello, Sam !
>>> customer_name = "Mr Peter Clark"    #imagine this info came from a database
>>> # ...
>>> say_hello(customer_name)
Hello, Mr Peter Clark !
>>>

在上面的例子中,my_name就像say_hello函数的任何局部变量;这让函数在被调用时可以定义它将如何处理这个值。
在运行时,函数可以用一个直接的值(在逻辑中“硬编码”的值,比如例子中的"Sam")或用另一个变量的值(比如customer_name)来调用。在这两种情况下,函数的my_name变量都会被赋予某个值,分别是"Sam"和"Mr Peter Clark"。在后者的情况下,这个值就是customer_name变量的内容。注意,函数内部使用的变量名(my_name)和调用函数时的变量名(customer_name)不需要相同。(这些分别被称为“形式参数”和“实际参数”)

需要注意的是,虽然通常大多数参数作为输入传递给函数,在某些情况下,它们可以作为输出,也就是说,可以在调用函数的逻辑层面提供新的或修改过的值。这样做需要使用适当的调用约定(见下面的参数传递约定


现在... 在这个非常基础的参数理解之外,事情会稍微复杂一些(但不多)。我将一般性地讨论这些额外的概念,并说明它们如何适用于Python。

参数的默认值(也叫“可选”参数)
当函数被声明时,可以为某些参数指定默认值。这些值用于在调用函数时没有指定的参数。显而易见,这些可选参数通常放在参数列表的最后(否则语言的编译器/解释器可能会很难搞清楚哪个参数是哪个...)

>>> def say_hello(dude = "Sir"):
...     print("Hello,", dude, "!")
...
>>> say_hello()
Hello, Sir !
>>> say_hello("William Gates")
Hello, Bill !            #just kidding ;-)
Hello, William Gates !   # but indeed. works as the original function when param
                         # is specified

可变数量的参数
在某些情况下,定义一个可以接受可变数量参数的函数是很方便的。虽然这些参数值最终会以某种容器(列表、数组、集合等)传递,但不同的语言提供了方便的方式来访问这些参数值。

>>> def add_many(operand1, *operands):
...    Sum = operand1
...    for op in operands:
...       Sum += op
...    return Sum
...
>>> add_many(1, 3, 5, 7, 20)
36
>>> add_many(1, 3)
4

命名参数(关键字参数)
在Python和其他一些语言中,调用函数时可以明确命名参数。虽然参数传递默认是基于位置的(“第一个参数、第二个参数”等),但Python允许你命名参数并以任何顺序传递它们。这主要是一种语法上的便利,但在接受很多参数的函数中,结合默认参数使用时会很有用。这也是一个很好的自我文档化的特性。

>>> def do_greetings(greeting, person):
...    print (greeting, "dear", person, "!")
...
>>> do_greetings(person="Jack", greeting="Good evening")
Good evening dear Jack !

在Python中,你甚至可以传递一个字典来代替多个命名参数,例如,使用do_greetingsas-is,想象你有一个字典,如下:

>>> my_param_dict = {"greeting":"Aloha", "person":"Alan"}

>>> do_greetings(**my_param_dict)
Aloha dear Alan !

最后,虽然传递参数的各种花哨方式,以及方法处理可变数量参数的能力是各种语言的有用特性,但有两个关键概念需要提到:

参数传递约定:按值或按引用
到目前为止,我们使用的所有函数都没有改变传递给它们的参数的值。然而,我们可以想象许多情况下,函数可能想要这样做,无论是为了对这些值进行某种转换或计算,还是为了有效地改变变量的值,以便在调用函数的逻辑层面反映这些变化。这就是参数传递约定派上用场的地方...
传递的参数可以被函数内部计算改变,但在调用方法的层面不会改变。
引用传递的参数会反映在调用方法的层面上所做的更改。
每种语言都规定了参数传递的方式。一个典型的约定是将整数、数值和其他基本类型按值传递,将对象按引用传递。大多数语言还提供关键字,允许改变它们的默认约定。

在Python中,所有参数都是按引用传递的。然而,有一些变量类型是不可变的(数字、字符串、元组等),因此它们不能被函数改变。

类方法的隐式“self”或“this”参数
在面向对象的语言中,方法(即类中的函数)会接收一个额外的参数,这个参数是底层对象的值(类的实例),允许方法在计算中使用类的各种属性成员,或改变这些属性的值。

在Python中,这个参数在方法定义时声明,但会隐式传递。虽然可以将其命名为任何想要的名字,但根据惯例,这个参数通常被称为self

>>> class Accumulator:
...   def __init__(self, initialValue = 0):
...        self.CurValue = initialValue
...   def Add(self, x):
...        self.CurValue += x
...        return self.CurValue
...
>>> my_accu = Accumulator(10)
>>> my_accu.Add(5)
15
>>> my_accu.Add(3)
18
10

简单来说,参数就是传递给函数的数据,用来告诉它该怎么做。维基百科上有更详细的介绍。

http://en.wikipedia.org/wiki/Function_argument

比如,你的 hi() 函数可能需要知道要向谁打招呼:

def hi(person):
    print "Hi there " + person + ", how are you?"

或者一个数学函数可能需要一个值来进行运算:

def square(x):
     return x * x

撰写回答