python:构造函数参数表示法

时间:2015-12-14 22:40:27

标签: python pyramid

我学习python几个月了。 在浏览金字塔教程后,我无法理解 init .py中的一行

from pyramid.config import Configurator
from sqlalchemy import engine_from_config

from .models import (
    DBSession,
    Base,
    )



def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    config = Configurator(settings=settings)
    config.include('pyramid_chameleon')
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
    config.scan()
    return config.make_wsgi_app()

我在配置器参数中丢失了settings = settings。

这是什么告诉python?

4 个答案:

答案 0 :(得分:4)

Python函数支持关键字参数:

def add(a, b):
    return a + b

add(a=1, b=2)

这发生在这里。

 Configurator(settings=settings)

第一个settings__init__ Configurator中参数的名称。第二个是当前名称空间中对象的名称。

答案 1 :(得分:2)

Python支持调用任何可调用对象(即函数,构造函数,甚至理解__call__方法的对象),指定位置参数,命名参数,甚至两种类型的参数。

当你传递命名参数时,它们必须是之后位置参数(如果有的话)。

所以你可以调用任何函数,例如:

def f(a, b):
    return a + b

通过以下方式:

f(1, 2)
f(1, b=2)
f(a=1, b=2)
f(b=1, a=2) # Order doesn't matter among named arguments

以下表单会触发错误:

f(a=1, 2) # Named arguments must appear AFTER positional arguments
f(1, a=2) # You are passing the same argument twice: one by position, one by name

因此,当您传递一个命名参数时,请确保不要两次传递相同的参数(即也按位置),并检查参数名称是否存在(另外:如果记录参数可以/应该按名称传递,尊重继承/覆盖的名称。

另外 Python支持传递*arguments**keyword_arguments。这些是您可以以可变方式处理的其他参数,因为许多语言都支持它们。

*args(名称无关紧要 - 它必须有一个星号作为位置可变参数;它是一个元组)保存剩余的不匹配的位置参数(而不是获取TypeError为位置参数是意外的,这样的参数作为元素进入*args

**kwargs(名称无关紧要 - 它必须有两个星号作为命名/关键字可变参数;它是一个字典)保存剩余的不匹配的命名参数(而不是获取命名参数的TypeError是意外的,这样的参数作为元素进入**kwargs

所以,也许你会看到这样的函数:

def f(*args, **kwargs):
    ...

您可以使用您想要的任何参数调用它:

f(1, 2, 3, a=4, b=5, c=6)

保持顺序:命名参数在位置参数之后

你可以声明一个这样的函数:

f(m1, m2, ..., o1=1, o2=2, ..., *args, **kwargs):
    pass

了解以下内容:

  • m1,m2,... 强制性:当您致电时,您必须按位置填写或尊重他们的名字。
  • o1,o2,...是可选:当你打电话时,你可以省略这些参数(省略它们意味着不按位置或按名称传递它们),并且它们将保留之后的值等号(在声明函数时评估此值 - 避免使用可变对象作为其值)。
  • args和kwargs就是我之前解释过的:按位置和名称进行的任何不匹配的参数都会进入这些参数。通过这些功能,您可以清楚地区分什么是参数和什么是参数。
  • 所有这些参数都是可选的。您可以选择不使用强制性和仅选项。您可以选择不使用*args,而是使用**kwargs,等等。但尊重声明中的顺序:必填,可选,*args**kwargs

当你调用方法并传递参数时,语义是非常不同的所以要警惕:

f(1) # passes a positional argument. Has nothing to do with the parameter being mandatory.
f(a=1) # passes a named argument. Has nothing to do with the parameter being optional.
f(**i) # UNPACKS the positional arguments. Has nothing to do with the function having a *args parameter, but *args will hold any unpacked -but unmatched- positional argument from i (which is any type of sequence or generator)
f(**d) # UNPACKS its values as named arguments. Has nothing to do with the function having a **kwargs parameter, but **kwargs will hold any unpacked -but unmatched- argument from d (which is a dict having string keys).

当您拨打电话时,您可以根据需要传递它们,这与实际方法签名无关(即预期参数),但尊重订单与参数一样:位置,命名,* positionalUnpack,** keywordUnpack,或者你会得到一个不错的TypeError

示例:

def f(a, b=1, *args, **kwargs):
    pass

有效来电:

f(1) # a = 1, b = 2, args = (), kwargs = {}
f(*[1]) #a = 1, b = 2, args = (), kwargs = {}
f(*[3, 4]) #a = 3, b = 4, args = (), kwargs = {}

f(**{'a':1, 'b':3}) #a = 1, b=3, args = (), kwargs = {}
f(1, *[2, 3, 4], **{'c': 5}) #a = 1, b=2, args=(3, 4), kwargs = {'c': 5}

再次提防:

  • 不要两次传递相同的参数(**解包参数与其他命名参数或位置参数或*解压缩参数之间会发生冲突)。
  • 如果您想将* args或** kwargs传递给super调用,请确保使用解包语法:

    def my_method(self, a, b, *args, **kwargs):
        super(MyClass, self).my_method(a+1, b+1, *args, **kwargs)
    

答案 2 :(得分:1)

这意味着您将参数设置传递给配置器,其中包含一个名为设置的变量

这里有一个例子,你有一个功能:

def function_test(a=None, b=None, c=None):
    pass

你可以这样称呼它:

c = "something"
function_test(c=c)

表示您在函数 function_test

中传递了您作为参数 c 的参数创建的变量 c

答案 3 :(得分:1)

它说它在settings中传递了本地名称settings作为名为Configurator的参数。

对于x=y形式的函数或构造函数调用,x是函数/构造函数端本地使用的参数名称,而y是调用者端的名称。在这种情况下,它们恰好是同一个名字。