Обозначение аргумента python: конструктор

Через несколько месяцев я изучу 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()

Я потерял настройки = настройки в аргументе configurator.

Что это за говорящий python?

+6
источник поделиться
4 ответа

Функции Python поддерживают аргументы ключевого слова:

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

add(a=1, b=2)

Это происходит здесь.

 Configurator(settings=settings)

Первый settings - это имя параметра в __init__ of Configurator. Второй - это имя для объекта в текущем пространстве имен.

+4
источник

Это означает, что вы передаете аргумент настройки в Конфигуратор, который содержит переменную с именем настройки

вот пример, у вас есть функция:

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

Вы могли бы так называть:

c = "something"
function_test(c=c)

означающий, что вы передали переменную c, которую вы создали в качестве аргумента для параметра c в функции function_test

+1
источник

Он говорит, что он передает локальное имя settings в качестве аргумента с именем settings в Configurator.

Для вызова функции или конструктора формы x=y x - это имя аргумента, используемое локально на стороне функции/конструктора, а y - это имя на стороне вызывающего абонента. В этом случае они просто одно и то же.

+1
источник

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 (имя не имеет значения - оно должно иметь две звездочки как именованное/ключевое слово variadic, это словарь) содержит оставшиеся непревзойденные именованные аргументы (вместо того, чтобы получить 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).

Когда вы совершаете вызов, вы можете передавать их по своему усмотрению, что не имеет никакого отношения к фактической сигнатуре метода (т.е. ожидаемым параметрам), но соблюдает порядок как с параметрами: positional, named, * 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)
    
+1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос