位置参数与关键字参数

130

基于this

位置参数是指没有跟随等号(=)和默认值的名称。

关键字参数是指跟随等号和给出默认值的表达式。

def rectangleArea(width, height):
    return width * height

    
print rectangleArea(width=1, height=2)

问题。我假设widthheight都是位置参数。那么为什么我们也可以使用关键字参数语法来调用它呢?

4
为什么我们也可以用关键字实参语法来调用它?因为这是该语言的工作方式。 - S.Lott
9个回答

200
那段你引用的文本似乎混淆了两个完全不同的东西: 我怀疑编写该课件的人对 Python 不是非常熟悉 :-) 因此你提供的链接质量并不是很好。
在您调用函数时,您使用了“关键字参数”功能(其中参数是命名的,而不是依赖于其位置)。如果没有这个功能,值仅基于顺序绑定到名称。因此,在此示例中,下面的两个调用是等效的:
def process_a_and_b(a, b):
   blah_blah_blah()

process_a_and_b(1, 2)
process_a_and_b(b=2, a=1)

举个例子,参考以下定义和调用:

def fn(a, b, c=1):        # a/b required, c optional.
    return a * b + c

print(fn(1, 2))            # returns 3, positional and default.
print(fn(1, 2, 3))         # returns 5, positional.
print(fn(c=5, b=2, a=2))   # returns 9, named.
print(fn(b=2, a=2))        # returns 5, named and default.
print(fn(5, c=2, b=1))     # returns 7, positional and named.
print(fn(8, b=0))          # returns 1, positional, named and default.

4
在这个语境中,named 的意思等同于 keyword - Fredrick Gauss
你说:“在调用那个函数时,你正在使用“命名参数”的特性。”。但接着你又说:“Python参考只涉及到对函数的调用中的位置和关键字参数。”。所以,现在我很困惑:何时会出现位置参数和关键字参数?因为正如你所说,在函数调用中它们会变成位置参数或命名参数。提前致谢! - Milan
1
@Milan(和Fredrick),我在Python中使用“命名”可能是不恰当的,应该使用“关键字” - 我已经修正了这个问题。在选择位置参数/关键字参数时,它发生在调用时(而不是定义时),取决于是否使用 fn(10) 还是 fn(param=10) 等因素。在函数定义中,= 的存在与位置参数/关键字参数无关。 - paxdiablo

112

定位参数、关键字参数、必需参数和可选参数经常被混淆。 定位参数必需参数不同,关键字参数可选参数不同。

定位(只)参数绑定到调用中提供的位置参数,即按位置顺序。它们在Python 3.8中引入。

关键字(只)参数绑定到在调用中提供的关键字参数,即按名称。

定位或关键字参数绑定到在调用中提供的位置参数或关键字参数,即按位置或按名称。

必需参数绑定到在调用中提供的参数。

可选参数绑定到在定义中提供的默认参数。

这是声明参数的Python语法:

def f(positional_parameter, /, positional_or_keyword_parameter, *, keyword_parameter):
    pass
  • Python 3.8 开始需要使用的位置参数:

def f(a, /):
    pass


f()  # error, argument is required
f(1)  # allowed, positional argument
f(a=1)  # error, keyword argument
  • 位置可选参数(自Python 3.8起):

  • def f(a=2, /):
        pass
    
    
    f()  # allowed, argument is optional
    f(1)  # allowed, positional argument
    f(a=1)  # error, keyword argument
    
  • 必需的关键字参数:

  • def f(*, a):
        pass
    
    
    f()  # error, argument is required
    f(1)  # error, positional argument
    f(a=1)  # allowed, keyword argument
    
  • 可选的关键字参数:

    def f(*, a=1):
        pass
    
    
    f()  # allowed, argument is optional
    f(1)  # error, positional argument
    f(a=1)  # allowed, keyword argument
    
  • 必需的位置参数或关键字参数:

  • def f(a):
        pass
    
    
    f()  # error, argument is required
    f(1)  # allowed, positional argument
    f(a=1)  # allowed, keyword argument
    
    
    # In fact that function is the same as this one.
    
    def f(/, a, *):
        pass
    
  • 可选的位置或关键字参数:

    def f(a=1):
        pass
    
    
    f()  # allowed, argument is optional
    f(1)  # allowed, positional argument
    f(a=1)  # allowed, keyword argument
    
    
    # In fact that function is the same as this one.
    
    def f(/, a=1, *):
        pass
    
  • 结论。 — 参数可以是必需的或可选的,但不能同时为必需和可选。它也可以是位置参数、关键字参数或同时为两者


    2
    你的最后两个例子中,是不是想表达 f(/,a,*) 而不是 f(*, a, /) - Jagerber48
    15
    请解释一下你的函数中的 "/" 是什么意思。 - Lord-shiv
    1
    @Lord-shiv 它表示位置参数的结束,这些参数不能用作关键字参数。根据 https://dev59.com/sGAf5IYBdhLWcg3wXhoJ - marticztn

    21

    关键字参数就是带有默认值的位置参数。必须指定所有没有默认值的参数。换句话说,关键字参数之所以“可选”,是因为如果未明确提供,则将设置为它们的默认值。


    好的,这很有道理,但你能详细解释一下为什么它被称为“关键字”参数吗?我知道“位置”参数意味着在调用函数时它们的位置很重要。 - NoName

    11
    首先,“参数”是函数/方法定义中指定参数的命名实体。而“参数值”则是传递给函数的数值。
    例如:
    def rectangle_area(height, width):
        pass
    
    rectangle_area(argument_1, argument_2)
    

    heightwidth是函数参数,argument_1argument_2是传递给函数的参数。当你说位置参数时,你说的是参数,这与函数定义无关。widthheight(在Python中默认情况下)是位置参数或关键字参数(即所谓的位置或关键字参数)。因此,您可以通过位置或关键字传递参数。

    您如何调用/传递值到函数决定它们是否为位置参数或关键字参数

    对于函数rectangle_area,我们可以这样平等地调用它:

    rectangle_area(1, 2) # positional arguments
    rectangle_area(width=2, height=1) # keyword arguments
    
    • 在第一次调用中,我们按位置传递了值:1被传递给高度参数,2被传递给宽度参数。也就是说,当你使用1, 2时,Python根据它们被传递的位置(即函数定义中第一个参数是高度,第二个参数是宽度)推断出我们的意思。
    • 在第二次调用中,我们通过关键字传递了值。我们向Python提示我们将参数传递给哪个参数。在第二个例子中,我们颠倒了参数的顺序,但是我们告诉Python高度仍然是1,宽度仍然是2。这两个调用具有完全相同的结果。

    仅限位置和仅限关键字

    很少有人知道的是,您可以在参数列表中使用/指定仅限位置参数(来自这里的示例)。

    def func(positional_only1, positional_only2, /, positional_or_keyword): ...
    

    同样地,你也可以通过使用 * 字符来实现仅限关键字参数。

    def func(positional_or_keyword, *, keyword_only1, keyword_only2): ...
    

    最后,我们还有可变位置参数和可变关键字参数(也就是 *args 和 **kwargs)。这意味着您可以将任意数量的位置参数或关键字参数传递给函数。


    1

    位置参数:按正确的位置顺序传递给函数的参数。以下程序了解函数的位置参数。

    #positional arguments example
    def combine(str1, str2):
    #To join str1 and str2 with str3
        str3 = str1 + str2
        print(str3)
    
    #call combine() and pass 2 strings
    combine("Well", "come")   #positional arguments 
    

    假设我们先传递'come',然后是'well',那么结果将是comewell。另外,调用函数时如果传入3个字符串会导致错误。

    1

    位置参数可以按顺序使用值或通过命名每个参数来调用。例如,以下三种方式都可以达到相同的效果:

    def rectangleArea(width, height):
        return width * height
    
    print(rectangleArea(1, 2))
    print(rectangleArea(width=1, height=2))
    print(rectangleArea(height=2, width=1))
    

    1
    我认为这不正确。根据Python官方词汇表此处的定义,位置参数是一个不是关键字参数的参数。而关键字参数的定义是在函数调用中由标识符(例如name=)引导的参数,或者在字典中作为值传递并由**引导。这两个定义与您的示例相矛盾。 - Rafael

    0
    我假设宽度和高度均为位置参数。那么为什么我们也可以使用关键字参数语法进行调用?
    要防止这种情况,您可以使用位置参数限定:
    def rectangleArea(width, height, /):
        return width * height
    
    print rectangleArea(width=1, height=2)
    

    错误信息如下:

    TypeError: rectangleArea() 作为关键字参数传递了一些位置参数:'width, height'


    0

    了解函数的关键字参数。

    关键字参数是通过其名称来标识参数的参数。

    #keyword arguments example: 
    def employee(name, Id):
        print("Employee Name: ", name)
        print("Employee Id  : ", Id)
    #call employee() and pass 2 arguments
    employee(name = "inban", Id = "pay001")
    employee(Id = "pay002", name = "karthik") #we can change the order args.
    

    0

    这里有一些额外的信息,以补充@Nazime Lakehal的优秀答案

    一个可选的位置参数不能跟在一个必需的位置参数或位置-关键字参数后面:

    # SyntaxError.
    
    def f(a=1, b, /):
        pass
    
    
    # SyntaxError.
    
    def f(a=1, /, b):
        pass
    

    一个可选的位置参数或关键字参数后面不能跟着一个必须的位置参数或关键字参数:
    # SyntaxError.
    
    def f(a=1, b):
        pass
    

    对于绑定可选的位置参数,必须先绑定所有前面的可选位置参数,使它们都成为实际上的必需参数。这可能是将位置参数与必需参数混淆的起因:

    def f(a=1, b=2, /):
        pass
    
    
    f(1, 0)
    

    对于绑定一个可选的关键字参数或位置-关键字参数,所有其他可选的关键字参数和位置-关键字参数都不必被绑定。这可能是将关键字参数与可选参数混淆的起源:

    def f(c=3, *, a=1, b=2):
        pass
    
    
    f(b=0)
    
    
    def f(a=1, b=2, *, c=3):
        pass
    
    
    f(b=0)
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接