Ale*_*rry 0 python arguments language-design function argument-passing
什么是[函数]参数?它们用于什么?
我最近开始学习Python; 我是编程的新手,我为这个基本问题道歉.
在每个Python教程中,我都会讨论参数.我已经找到了这个问题的答案,并找到了很多答案,但对我来说,这些答案有点难以理解.我可能只是缺少一些概念背景.
所以...当我定义一个函数时,括号中的东西用于什么?例:
def hi( This is the part that i dont get):
print 'hi'
Run Code Online (Sandbox Code Playgroud)
编辑:
与此相关的两个后续问题后来在这里被关闭和合并,因此部分答案的部分脱离背景特征.
后续问题是:[转述]
dus*_*uff 10
简而言之,它们是"传递"到函数中的数据,告诉它该做什么.维基百科有详细信息.
http://en.wikipedia.org/wiki/Function_argument
例如,您的hi()函数可能需要知道向谁打招呼:
def hi(person):
print "Hi there " + person + ", how are you?"
Run Code Online (Sandbox Code Playgroud)
或者数学函数可能需要一个值来操作:
def square(x):
return x * x
Run Code Online (Sandbox Code Playgroud)
这不是一个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
Run Code Online (Sandbox Code Playgroud)
在编写程序时,不需要知道ball_radius的实际值; 然而,假设该变量将包含某个假想球的数值,该片段能够描述如何计算球的体积.以这种方式,当程序运行时,以某种方式(稍后更多)ball_radius变量已经初始化了一些适当的值,变量ball_volume也可以初始化和使用,这里在条件语句(if)中,并且可能下面.(在某些时候,变量可能超出范围,但是这个控制程序何时可以访问特定变量的概念远远超出了这个引子).
在某些语言中,可能需要明确定义可能与特定变量关联的数据类型,并且不能更改.例如,一些变量只能包含整数值,其他变量可以包含字符串值(文本)等.在Python中没有这样的限制,可以为一个变量分配并重新分配给任何类型的数据,但当然,程序员需要例如,记住这一点以避免将一些文本数据传递给数学函数.
存储在变量中的数据可能来自非常不同的来源.教程和介绍性文档中提供的许多示例都是来自键盘输入的数据(如使用某些问题中提到的raw_input时).这是因为它允许人们尝试这些教程片段进行交互式测试.但是,如果变量仅从交互式用户输入中获取数据,则程序的有用性将相当有限.还有许多其他来源,这就是使编程如此强大的原因:可以使用以下数据初始化变量:
简而言之,Arguments(也称为Parameters)是传递给函数的变量,[通常]用于从函数中提供不同的输出和行为.例如:
>>> 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 !
>>>
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,my_name就像say_hello函数的任何局部变量一样; 这允许函数在运行时定义在调用函数时它将对底层值执行的操作.
在运行时,可以使用立即值(在逻辑中"硬编码"的值,例如"Sam"在示例中)或使用[另一个变量的值](例如customer_name)来调用函数.在这两种情况下,函数的my_name变量的值分别被赋予一些值,"Sam"和"Mr Peter Clark".在后一种情况下,该值是customer_name变量包含的值.请注意,函数()内部和函数调用时使用的变量名称my_name(customer_name)不需要相同.(这些分别称为"形式参数"和"实际参数")
请注意,虽然通常大多数参数作为函数的输入传递,但在某些情况下,它们可以用作输出,即在调用函数的逻辑级别提供新的/修改的值.这样做需要隐式或显式地使用正确的调用约定规范(见Argument passing conventions下文)
现在......除了对参数目的的这种非常基本的理解之外,事情变得比这更复杂(但并不多).我将一般性地讨论这些附加概念,并在它们适用于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
Run Code Online (Sandbox Code Playgroud)
可变数量的参数
在某些情况下,定义一个函数以便它可以接受可变数量的参数可能很方便.虽然这些参数值列表最终在某种容器(列表,数组,集合......)中传递,但各种语言提供了访问这些参数值的便捷方式.
>>> 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
Run Code Online (Sandbox Code Playgroud)
命名参数(关键字参数)
使用Python和一些其他语言,可以在调用函数时显式命名参数.因此,默认情况下,参数传递是基于位置基础("第一个参数,第二个参数等"),Python将允许您命名参数并以任何顺序传递它们.这主要是语法精确,但可以是有用的,结合使用接受很多参数的函数的默认参数.它也是一个很好的自我记录功能.
>>> def do_greetings(greeting, person):
... print (greeting, "dear", person, "!")
...
>>> do_greetings(person="Jack", greeting="Good evening")
Good evening dear Jack !
Run Code Online (Sandbox Code Playgroud)
在Python中,您甚至可以通过字典代替几个命名参数,例如,使用do_greetingsas-is,假设您有一个字典,如:
>>> my_param_dict = {"greeting":"Aloha", "person":"Alan"}
>>> do_greetings(**my_param_dict)
Aloha dear Alan !
Run Code Online (Sandbox Code Playgroud)
最后,虽然传递参数的奇特方式以及处理可变数量参数的方法的能力是各种语言的有用特性,但需要提到两个关键概念:
参数传递约定:通过值或引用
到目前为止,我们使用的所有函数都没有改变传递给它们的参数的值.我们可以想象许多实例,当函数可能想要这样做时,要么对所述值执行一些转换或计算,为了它自己的内部使用,要么有效地改变变量的值,以便更改反映在该级别调用函数的逻辑.这就是参数传递约定变得方便的地方...... 通过值
传递的参数可能会被函数更改为自己的内部计算,但不会在调用方法的级别上更改.通过引用
传递的参数将反映在调用方法级别对它们所做的更改.
每种语言都指定了传递参数的方式.典型的约定是按值传递整数,数字值和其他基本类型,并通过引用传递对象.大多数语言还提供允许更改其默认约定的关键字.
在python中,所有参数都通过引用传递.但是,一些变量类型是不可变的(数字,字符串,元组......),因此它们不能被函数改变.
类方法的隐式"self"或"this"参数
在面向对象的语言中,方法(即类中的函数)接收额外的参数,该参数是底层对象(类的实例)的值,允许该方法使用各种在计算中属性类的成员和/或改变其中一些属性的值.
在Python中,此参数在方法定义的级别声明,但是隐式传递.被宣布后,它可能被命名为任何人所希望的,尽管按照惯例,这通常称为自我.
>>> 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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,使用参数,它只是一个如何使用它们的演示,而不是你演示的最有效.功能非常有用.例如,如果我想添加两个数字:
def add(num1, num2):
x = num1 + num2
return x
add(1,3)
Run Code Online (Sandbox Code Playgroud)
函数对于执行重复性任务非常有用,比方说在你的例子中你必须向数百个名称打个招呼,而不是必须执行该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)
>>>
Run Code Online (Sandbox Code Playgroud)
祝你好运!如果您需要进一步的帮助,请随时给我发电子邮件(sbrichards(at)mit.edu)