函数参数(例如在Python中)
[函数]的参数是什么?它们有什么用?
我最近刚开始学习Python;我对编程还很陌生,抱歉问这个基础问题。
在我看的每一个Python教程中,他们都会提到参数。我查找过这个问题的答案,发现了很多答案,但对我来说有点难以理解。可能是我缺少一些基本概念的背景知识。
那么……当我定义一个函数时,括号里的东西是用来干什么的呢?举个例子:
def hi( This is the part that i dont get):
print 'hi'
补充:
与这个问题相关的两个后续问题后来被关闭并合并到这里,因此一些答案可能有点不在上下文中。
这些后续问题是:[意译]
- 参数只能用于输入吗?
还有其他使用参数的例子吗? - 为什么要使用参数,而不是让函数直接调用raw_input?
- 为什么参数传递的概念被描述为如此强大?在我看来,我们只是用它们来替代用户在键盘上输入的内容。
8 个回答
在这种情况下,使用参数只是一个演示,告诉你怎么用它们,可能不是最有效的方式,就像你展示的那样。函数非常有用。比如说,如果我想加两个数字:
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)
这不是一个关于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
简单来说,参数就是传递给函数的数据,用来告诉它该怎么做。维基百科上有更详细的介绍。
http://en.wikipedia.org/wiki/Function_argument
比如,你的 hi()
函数可能需要知道要向谁打招呼:
def hi(person):
print "Hi there " + person + ", how are you?"
或者一个数学函数可能需要一个值来进行运算:
def square(x):
return x * x