Какие параметры являются позиционными а какие именованными
Перейти к содержимому

Какие параметры являются позиционными а какие именованными

  • автор:

Именованные и необязательные аргументы (Руководство по программированию на C#)

Именованные аргументы позволяют указать аргумент для параметра, связав этот аргумент с именем параметра, а не с его позицией в списке параметров. Необязательные аргументы позволяют опускать аргументы для некоторых параметров. Оба варианта можно использовать с методами, индексаторами, конструкторами и делегатами.

При использовании именованных и необязательных аргументов аргументы оцениваются в том порядке, в котором они отображаются в списке аргументов, а не в списке параметров.

Именованные и дополнительные параметры позволяют указать аргументы для выбранных параметров. Эта возможность значительно упрощает вызов интерфейсов COM, таких как API автоматизации Microsoft Office.

Именованные аргументы

Именованные аргументы освобождают от сопоставления порядка аргументов с порядком параметров в списках параметров вызываемых методов. Аргумент каждого параметра можно указать по имени параметра. Например, функция, которая выводит сведения о заказе (имя продавца, номер заказа и наименование товара и т. д.), может вызываться путем передачи аргументов по позиции в порядке, определяемом функцией.

PrintOrderDetails("Gift Shop", 31, "Red Mug"); 

Если вы не помните порядок параметров, но знаете их имена, можете передать аргументы в любом порядке.

PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop"); PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31); 

Именованные аргументы также делают код более удобным для чтения, поскольку указывают, чему соответствует каждый аргумент. В приведенном ниже примере метода sellerName не может быть равен NULL или пробелу. Так как и sellerName , и productName являются строковыми типами, вместо передачи аргументов по позиции имеет смысл использовать именованные аргументы, чтобы устранить данную неоднозначность и сделать код более удобочитаемым.

Именованные аргументы при использовании с позиционными аргументами допустимы при условии, что

    за ними не следуют позиционные аргументы, либо,

PrintOrderDetails("Gift Shop", 31, productName: "Red Mug"); 
PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug"); 

Позиционные аргументы после внеочередных именованных аргументов недопустимы.

// This generates CS1738: Named argument specifications must appear after all fixed arguments have been specified. PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop"); 

Пример

Приведенный ниже код реализует как примеры из этого раздела, так и некоторые дополнительные примеры.

class NamedExample < static void Main(string[] args) < // The method can be called in the normal way, by using positional arguments. PrintOrderDetails("Gift Shop", 31, "Red Mug"); // Named arguments can be supplied for the parameters in any order. PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop"); PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31); // Named arguments mixed with positional arguments are valid // as long as they are used in their correct position. PrintOrderDetails("Gift Shop", 31, productName: "Red Mug"); PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug"); PrintOrderDetails("Gift Shop", orderNum: 31, "Red Mug"); // However, mixed arguments are invalid if used out-of-order. // The following statements will cause a compiler error. // PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop"); // PrintOrderDetails(31, sellerName: "Gift Shop", "Red Mug"); // PrintOrderDetails(31, "Red Mug", sellerName: "Gift Shop"); >static void PrintOrderDetails(string sellerName, int orderNum, string productName) < if (string.IsNullOrWhiteSpace(sellerName)) < throw new ArgumentException(message: "Seller name cannot be null or empty.", paramName: nameof(sellerName)); >Console.WriteLine($"Seller: , Order #: , Product: "); > > 

Необязательные аргументы

Определение метода, конструктора, индексатора или делегата может указывать, являются его параметры обязательными или нет. Любой вызов должен содержать аргументы для всех обязательных параметров; аргументы для необязательных параметров можно опустить.

Определение каждого необязательного параметра содержит его значение по умолчанию. Если аргумент для параметра не передается, используется значение по умолчанию. Значением по умолчанию должен быть один из следующих типов выражений:

  • константное выражение;
  • выражение в форме new ValType() , где ValType — это тип значения, например, enum или struct;
  • выражение в форме default(ValType), где ValType — это тип значения.

Необязательные параметры определяются в конце списка параметров после всех обязательных параметров. Если вызывающий объект предоставляет аргумент для любого из последующих необязательных параметров, он должен содержать аргументы для всех предыдущих необязательных параметров. Пробелы, разделенные запятыми, в списке аргументов не поддерживаются. Например, в следующем коде метод экземпляра ExampleMethod определяется одним обязательным и двумя необязательными параметрами.

public void ExampleMethod(int required, string optionalstr = "default string", int optionalint = 10) 

Следующий вызов ExampleMethod вызывает ошибку компилятора, поскольку аргумент предоставляется для третьего параметра, но не для второго.

//anExample.ExampleMethod(3, ,4); 

Если вы знаете имя третьего параметра, можете использовать для выполнения задачи именованный аргумент.

anExample.ExampleMethod(3, optionalint: 4); 

В IntelliSense необязательные параметры заключаются в квадратные скобки, как показано на следующем рисунке:

Screenshot showing IntelliSense quick info for the ExampleMethod method.

Необязательные параметры также можно объявлять с помощью класса .NET OptionalAttribute. Для параметров OptionalAttribute значение по умолчанию не требуется. Однако если нужное значение по умолчанию, ознакомьтесь с DefaultParameterValueAttribute классом.

Пример

В следующем примере конструктор ExampleClass имеет один параметр, который является необязательным. У метода экземпляра ExampleMethod есть один обязательный параметр, required , и два необязательных параметра, optionalstr и optionalint . Код в Main демонстрирует различные способы, которые можно использовать для вызова конструктора и метода.

namespace OptionalNamespace < class OptionalExample < static void Main(string[] args) < // Instance anExample does not send an argument for the constructor's // optional parameter. ExampleClass anExample = new ExampleClass(); anExample.ExampleMethod(1, "One", 1); anExample.ExampleMethod(2, "Two"); anExample.ExampleMethod(3); // Instance anotherExample sends an argument for the constructor's // optional parameter. ExampleClass anotherExample = new ExampleClass("Provided name"); anotherExample.ExampleMethod(1, "One", 1); anotherExample.ExampleMethod(2, "Two"); anotherExample.ExampleMethod(3); // The following statements produce compiler errors. // An argument must be supplied for the first parameter, and it // must be an integer. //anExample.ExampleMethod("One", 1); //anExample.ExampleMethod(); // You cannot leave a gap in the provided arguments. //anExample.ExampleMethod(3, ,4); //anExample.ExampleMethod(3, 4); // You can use a named parameter to make the previous // statement work. anExample.ExampleMethod(3, optionalint: 4); >> class ExampleClass < private string _name; // Because the parameter for the constructor, name, has a default // value assigned to it, it is optional. public ExampleClass(string name = "Default name") < _name = name; >// The first parameter, required, has no default value assigned // to it. Therefore, it is not optional. Both optionalstr and // optionalint have default values assigned to them. They are optional. public void ExampleMethod(int required, string optionalstr = "default string", int optionalint = 10) < Console.WriteLine( $": , , and ."); > > // The output from this example is the following: // Default name: 1, One, and 1. // Default name: 2, Two, and 10. // Default name: 3, default string, and 10. // Provided name: 1, One, and 1. // Provided name: 2, Two, and 10. // Provided name: 3, default string, and 10. // Default name: 3, default string, and 4. > 

Приведенный выше код выводит число примеров с некорректно примененными необязательными параметрами. Первый пример демонстрирует, что для первого параметра (обязательный) необходимо указать аргумент.

COM-интерфейсы

Именованные и необязательные аргументы, а также поддержка динамических объектов значительно улучшают взаимодействие с API COM, такими как API автоматизации Office.

Например, метод AutoFormatв интерфейсе Microsoft Office Excel Range имеет семь параметров и все они необязательные. Эти параметры показаны на следующем рисунке:

Screenshot showing IntelliSense quick info for the AutoFormat method.

Однако можно значительно упростить вызов AutoFormat с помощью именованных и необязательных аргументов. Именованные и необязательные аргументы позволяют опускать аргументы для необязательных параметров, если значение параметра по умолчанию менять не нужно. В следующем вызове значение задается только для одного из семи параметров.

var excelApp = new Microsoft.Office.Interop.Excel.Application(); excelApp.Workbooks.Add(); excelApp.Visible = true; var myFormat = Microsoft.Office.Interop.Excel.XlRangeAutoFormat.xlRangeAutoFormatAccounting1; excelApp.Range["A1", "B4"].AutoFormat( Format: myFormat ); 

Разрешение перегрузки

Использование именованных и необязательных аргументов влияет на разрешение перегрузки описанным ниже образом.

  • Метод, индексатор или конструктор является кандидатом на выполнение, если каждый из его параметров необязателен либо по имени или позиции соответствует одному и тому же аргументу в операторе вызова, и этот аргумент можно преобразовать в тип параметра.
  • Если найдено более одного кандидата, правила разрешения перегрузки для предпочтительных преобразований применяются к аргументам, указанным явно. Опущенные аргументы для необязательных параметров игнорируются.
  • Если два кандидата определяются как равно подходящие, предпочтение отдается кандидату без необязательных параметров, аргументы которых в вызове были опущены. При разрешении перегрузки обычно используются кандидаты с меньшим числом параметров.

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Какие параметры являются позиционными а какие именованными

Функция может принимать параметры. Параметры перечисляются в скобках после имени функции имеют следующее определение:

тип название_параметра

Стоит отметить, что ранее уже использовалась одна функция, которая принимает параметры — это функция print() . Она через параметр принимает некоторое значение и выводит его на консоль. И благодаря параметру мы можем передавать в функцию различные значения и выводить их на консоль.

void main()

Определим свою функцию, которая принимает параметры. Пусть она складывает два числа:

void main() < sum(2, 5); // 7 >void sum(int a, int b)

Функция sum принимает два параметра, которые имеют имена a и b и представляют тип int . В функции main вызываем функцию sum и передаем ей два аргумента. Аргументы — это значения для параметров функции. Аргументы передаются параметрам по позиции. То есть первый аргумент передается первому параметру, второй аргумент — второму параметру и так далее. В данном случае параметр a в качестве значения получит число 2, а параметр b — число 5.

Количество передаваемых аргументов должно соответствовать количеству параметров. Кроме того между типами аргументов и типами параметров должно быть соответствие. Например, определим еще одну функцию:

void main() < printPerson("Tom", 35); printPerson("Alice", 29); >void printPerson(String name, int age)

Функция printPerson принимает два параметра. Первый параметр представляет тип String, а второй представляет тип int. Поэтому при вызове функции необходимо сначала передать значение типа String (то есть строку), а затем значение типа int (то есть целое число)

При определении функции мы можем не указывать тип параметров. Тогда Dart сам выводит их тип исходя из передаваемых значений:

void main() < printPerson("Tom", 35); printPerson(29, "Alice"); >void printPerson(name, age)

Обратите внимание, что теперь при определении функции неизвестно, какой именно тип представляют параметры name и age. Формально в качестве типа будет применяться dynamic . То есть предыдущее определение функци printPerson будет аналогично следующему:

void printPerson(dynamic name, dynamic age)

Поэтому во втором вызове функции printPerson(29, «Alice») Dart будет трактовать параметр name как параметр типа int, потому что ему передается целое число. А параметр age будет трактоваться как строка.

Необязательные параметры

Ряд параметров мы можем сделать необязательными, то есть мы можем не передавать для них никаких значений. Для этого параметр заключается в квадратные скобки. Но при этом ему необходимо предоставить значение по умолчанию, которое будет использоваться, если параметру не передано никакого значения:

void main() < printPerson("Tom", 35); printPerson("Alice"); >void printPerson(String name, [int age = 22])

В данном случае параметр age является необязательным. Если мы не передадим ему никакого значения, то он по умолчанию будет иметь значение 22. Консольный вывод:

Name: Tom Age: 35 Name: Alice Age: 22

Следует учитывать, что необязательные параметры, должны идти после обязательных. Так, в примере выше необязательный параметр age идет после обязательного параметра name.

Также может быть несколько необязательных параметров, и все помещаются в квадратные скобки:

void main() < printPerson("Tom"); >void printPerson(String name, [int age = 22, String company = «Undefined»])

В данном случае 2 необязательных параметра — age и company.

Однако если необязательный параметр представляет nullable-тип, то есть может принимать значение null, тогда можно не указывать для него значение по умолчанию — в этом случае значение по умолчанию будет null :

void main() < printPerson("Tom", 35); printPerson("Alice"); >void printPerson(String name, [int? age]) < print("Name: $name"); if(age!=null)< print("Age: $age \n"); >>
Name: Tom Age: 35 Name: Alice

Именованные параметры

Dart поддерживает передачу параметров по имени. Например:

void main() < printPerson(name: "Tom", age: 35); printPerson(age: 29, name: "Alice"); printPerson(name: "Kate"); >void printPerson()

При определении функции список параметров заключается в фигурные скобки, при этом для каждого параметра, если его тип не поддерживает значение null, указывается значение по умолчанию.

При вызове функции указывается имя параметра и через двоеточие его значение ( name: «Tom» ), при этом мы можем указывать параметры в любой последовательности. Например, во втором вызове вначале указывается значение для параметра age, а потом для параметра name ( printPerson(age: 29, name: «Alice») ). Более того мы можем вообще не передавать параметрам значение, тогда подобный параметр будет иметь значение по умолчанию, как в случае с параметром age в третьем вызове ( printPerson(name: «Kate») ).

Name: Tom Age: 35 Name: Alice Age:29 Name: Kate Age: 0

Если параметр представляет nullable-тип, то есть поддерживает значение null, то мы можем не указывать значение по умолчанию, тогда значением по умолчанию будет null:

void main() < printPerson(age: 35); printPerson(age: 29, name: "Alice"); printPerson(name: "Kate"); >void printPerson() < print("Name: $name"); if(age != null)< print("Age: $age \n"); >>

Консольный вывод программы:

Name: undefined Age: 35 Name: Alice Age: 29 Name: Kate

Обязательные параметры

Именнованные параметры по умолчанию необязательные. То есть мы можем указать для них значение по умолчанию, а при вызове функции не передавать этим параметрам значения. Однако иногда бывать необходимо, чтобы параметр был, с одной стороны, именованным, а, с другой стороны, обязательным. Для этого применяется оператор required , который указывается перед параметром. Например, сделаем обязательным параметр name:

void main() < printPerson(age: 29, name: "Alice"); printPerson(name: "Kate"); // printPerson(age: 35); // ! Ошибка - для name надо указать значение >void printPerson()

В этом случае для параметра name надо обязательно указать значение, при этом ему можно передать значение по имени.

Константы в функциях

Параметры позволяют передать значения локальным переменным, которые определены в функциях. Но также можно передавать через параметры значения локальным final -константам, поскольку они определяются во время выполнения. Но при этом мы не можем передавать значения const -константам, так как их значения должны известны уже во время компиляции. В связи с чем при разных вызовах функции мы можем передать final -константам разные значения:

void main() < printPerson("Tom", 35); printPerson("Alice", 22); >void printPerson(String userName, int userAge) < // const int initialAge = userAge; - так нельзя, константа должна определяться на этапе компиляции final String name = userName; final int age = userAge; print("Name: $name Age: $age \n"); >

Консольный вывод программы:

Name: Tom Age: 35 Name: Alice Age: 22

Позиционные аргументы — Python: Функции

У функций, которые мы изучали ранее, были в основном позиционные аргументы. Когда мы вызываем такие функции, значения в их аргументы подставляются согласно позиции их имен в определении функции. Например, мы вызываем следующую функцию:

def add(x, y): return x + y 

В этом случае с аргументами (10, 20) аргумент x получит значение 10 , а y — 20 .

Функция не всегда должна получать фиксированное количество аргументов. Когда нам нужна большая гибкость, мы можем передать в нее неограниченное количество аргументов. В этом уроке мы узнаем, как объявлять функции с разным количеством аргументов, и как передавать функции аргументы, которые упакованы в коллекцию.

Переменное количество аргументов

Функция print принимает то количество аргументов, которые мы ей передадим. Она даже работает, когда ее вызывают без аргументов.

Рассмотрим пример функции с неограниченным количеством аргументов:

def f(*args): print(type(args)) print(args) f() # => tuple # => () f(1, 'a', None, False) # => tuple # => (1, 'a', None, False) 

Эта функция отличается от функции с позиционными аргументами аргументом *args . Точнее оператором * . Он упаковывает все передаваемые в функцию аргументы от текущей позиции и до конца в переменную как кортеж.

Аргумент с оператором * забирает в себя все переданные значения. Если мы хотим использовать дополнительные аргументы, их нужно указать перед аргументом с оператором * , как показано в примере:

def f(x, *args): print(f'Первый аргумент: x>') for a in args: print(f'Другой аргумент из *args a>!') f('Programing language', 'Python', 'PHP', 'Java') # => Первый аргумент: Programing language # => Другой аргумент из *args Python! # => Другой аргумент из *args PHP! # => Другой аргумент из *args Java! f() # TypeError: f() missing 1 required positional argument: 'x' 

Здесь функция принимает несколько аргументов, но как минимум один должен быть передан всегда. Первый аргумент станет значением переменной x , а остальные сохранятся в *args . Так можно делать любое нужное количество обязательных аргументов.

Передача аргументов в форме коллекции

Иногда нужно сначала сформировать набор аргументов, а потом передать их функции. Допустим, прочитать аргументы из файла или получить другим программным способом. Здесь снова пригодится оператор * :

def sum(a, b): return a + b nums = [3, 4] sum(*nums) # 7 

Часть аргументов можно подставлять сразу в функцию и даже подставлять несколько коллекций сразу:

def greet(*names): for name in names: print(f'Hello, name>!') greet( 'Bob', *['Mary', 'Clair'], 'Sam', *('Henry', 'John') ) # => Hello, Bob! # => Hello, Mary! # => Hello, Clair! # => Hello, Sam! # => Hello, Henry! # => Hello, John! 

В приведенном примере мы передали в функцию greet набор аргументов и коллекций. При помощи оператора * функция greet вызывается с шестью аргументами: ‘Bob’, ‘Mary’, ‘Clair’, ‘Sam’, ‘Henry’ и ‘John’. Результатом этого кода будет шесть приветствий по одному для каждого аргумента. Они будут в том порядке, в котором их передали в функцию.

Выводы

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Аргументы вызова

Аргумент — значение, передаваемое в функцию/метод при её/его вывозе.

Аргументы и параметры — две разные сущности, которые не следует путать между собой.

При вызове аргументы перечисляются через запятую , .

После вызова значения аргументов становятся доступными из локальных (в теле функции) переменных.

В Питоне существуют два типа аргументов:

Именованные аргументы

На заметку
Обычно используется сокращённое название — kwargs (keyword arguments).

Это аргументы, передаваемые в вызов при помощи имени (идентификатора), либо словаря с его распаковкой при помощи ** .

# Здесь 3 и 5 - именованные аргументы.
complex(real=3, imag=5)
complex(**)
Позиционные аргументы

На заметку
Обычно используется сокращённое название — args (arguments).

Это аргументы, передаваемые в вызов в определённой последовательности (на определённых позициях), без указания их имён. Элементы объектов, поддерживающих итерирование, могут использоваться в качестве позиционных аргументов, если их распаковать при помощи * .

# Здесь 3 и 5 - позиционные аргументы.
complex(3, 5)
complex(*(3, 5))
Механизм обработки аргументов

Перед вызовом значения аргументов, представленные в виде выражений, вычисляются.

Если указаны именованные аргументы, то они приводятся к позиционным описанным далее способом.

1. Создаётся список пустых слотов по числу формальных параметров. Если существует N позиционных аргументов, то они будут помещены в первые N слотов. Далее для каждого именованного аргумента его имя используется для определения соответствующего слота (например, если имя совпадает с первым именем параметра, то используется первый слот и т.д.).

2. Если слот уже заполнен, возбуждается TypeError. В иных случаях значение аргумента помещается в слот (даже если при вычислении выражения получено None).

def func(a, b): 
print(a, b)


func(a=1, **)
# func() got multiple values for keyword argument 'a'

3. После того как будут обработаны все аргументы, незаполненные слоты заполняются значениями по умолчанию из определения функции.

Значения параметров по умолчанию вычисляются лишь единожды в процессе определения функции. Поэтому один и тот же объект изменяемого типа, например, список или словарь, используемый в качестве аргумента по умолчанию, будет использован во всех вызовах, где значение параметра не указано явно. Обычно таких ситуаций следует избегать.

def func(a, b, d=3, e=[]): 
e.append(0)
print(a, b, d, e)


func(1, b=2, e=[4]) # 1 2 3 [4, 0]
func(1, 2) # 1 2 3 [0]
func(1, 2) # 1 2 3 [0, 0]
func(1, 2) # 1 2 3 [0, 0, 0]

4. Если после этого остались незаполненные слоты, для которых не указано значение по умолчанию, возбуждается TypeError. Иначе заполненный список слотов используется в качестве списка аргументов для вызова.

На заметку

Детали реализации CPython. Существуют встроенные функции, позиционные аргументы которых в реальности не имеют имён, хотя могут быть проименованы в документации. Поэтому такие аргументы не могут быть адресованы как именованные. Примерами таких функций могут служить функции реализованные на Си, использующие PyArg_ParseTuple() для разбора аргументов.

Распаковка

Наверняка вам встречались записи вида *args , **kwargs при вызове функций. Звездочки в этом случае указывают на то, что объект дожен быть «распакован» в набор аргументов для вызываемой функции.

1. Если позиционных аргументов больше, чем слотов для формальных параметров и при этом не используется распаковка вида *имя , возбуждается TypeError. Если распаковка используется, то формальный параметр получает кортеж с избыточными позиционными аргументами (кортеж будет пустым, если избытка не наблюдается).

2. Если для любого из именованных аргументов не нашлось соответствующего по имени формального параметра и при этом не используется распаковка вида **имя , возбуждается TypeError. Если распаковка используется, то формальный параметр получает словарь с избыточными именованными аргументами (словарь будет пустым, если избытка не наблюдается).

Если используется распаковка вида *выражение , то выражение должно вычисляться в объект, поддерживающий итерирование. В этом случае элементы объекта трактуются как дополнительные позиционные аргументы. Если существуют позиционные аргументы x1, . xN и выражение вычисляется в последовательность y1, . yM — это эквивалентно вызову с позиционными аргументами M+N : x1, . xN, y1, . yM .

На заметку

Как следствие из вышесказанного: хотя распаковка вида *выражение может употребляться ПОСЛЕ именованных аргументов, обрабатывается такое выражение всё же ДО (то же касается и **выражение , о чём будет сказано ниже). Впрочем, на практике именованные аргументы не часто встречаются вместе с *выражение в одном вызове, а потому такие недоразумения редки.

def func(a, b): 
print(a, b)

add_args = (2,)
func(b=1, *add_args) # 2 1
func(a=1, *add_args) # TypeError
func(1, *add_args) # 1 2

Если используется распаковка вида **выражение , то выражение должно вычисляться в отображение, содержимое которого трактуется как дополнительные позиционные аргументы. Если имя будет обнаружено и в результате выражения и в явном указании аргумента, возбуждается TypeError.

def func(a, b): 
print(a, b)


func(a=1, **)
# func() got multiple values for keyword argument 'a'
Ограничение на количество аргументов
  • Начиная с +py3.7, количество аргументов, которые могут быть приняты функцией явно ограничено лишь стеком. До этого существовало ограничение в 255 элементов, при нарушении которого возбуждалось SyntaxError.
  • При использовании функцией *args , **kwargs , количество ограничено значением из sys.maxsize .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *