Передача аргументов C # vs Python

Каковы основные отличия, если таковые имеются, от правил передачи аргументов Python против правил передачи аргументов в C #?

Я очень хорошо знаком с Python и только начинаю изучать C #. Мне было интересно, могу ли я подумать о установленном правиле относительно того, когда объект передается по ссылке или по значению тот же для C #, что и на Python, или если есть некоторые ключевые различия, которые мне нужно иметь в виду.

  • Принудительное именование параметров в Python
  • Должен ли я добавить конечную запятую после последнего аргумента в вызове функции?
  • Что означает только звезда * в объявлении функции?
  • Оцениваются ли функции при передаче в качестве параметров?
  • В Python, что определяет порядок при итерации через kwargs?
  • Python: как передать аргументы функции __code__ функции?
  • Python встроен в CPP: как вернуть данные на CPP
  • Как я могу перечислять / перечислять все установленные приложения в Windows XP?
  • обертывание списка структур с помощью boost.python
  • Могу ли я переопределить виртуальную функцию C ++ в Python с Cython?
  • Segfault, когда import_array не совпадает с той же единицей перевода
  • Простой, но быстрый IPC-метод для приложения Python и C ++?
  • 5 Solutions collect form web for “Передача аргументов C # vs Python”

    C # передает параметры по значению, если вы не укажете, что вы хотите его по-другому. Если тип параметра является структурой, его значение копируется, в противном случае копируется ссылка на объект. То же самое касается возвращаемых значений.

    Вы можете изменить это поведение с помощью модификатора ref или out , который должен быть указан как в объявлении метода, так и в вызове метода. Оба изменяют поведение для этого параметра для передачи по ссылке. Это означает, что вы больше не можете передавать более сложные выражения. Разница между ref и out заключается в том, что при передаче переменной в параметр ref она должна быть инициализирована уже, а переменная, переданная в параметр out , не должна быть инициализирована. В методе параметр out обрабатывается как неинициализированная переменная и перед возвратом ему нужно присвоить значение.

    Проблема с вызовом Python: «pass-by-value» или «pass-by-reference» язык и сравнение с C, C # и т. Д. Заключается в том, что Python имеет другую концепцию того, как относятся данные. Python не легко вписывается в обычную дихотомию по значению или по ссылке, что приводит к путанице и «это вызов по значению!». «Нет, это вызов по ссылке, и я могу это доказать!» «НЕТ, ВАМ МАРКОН, это, очевидно, звонок по значению!» бесконечный цикл, свидетелем выше.

    Правда в том, что это не так. Python использует call-by-sharing (aka call-by-object). Иногда это похоже на стратегию по значению (например, при работе со скалярными значениями, такими как int , float и str ), а иногда и как эталонная стратегия (например, при работе со структурированными значениями, такими как list , dict , set и object ). Код Дэвида Гудгера, подобный Pythonista , прекрасно понимает это как «другие языки имеют переменные , у Python есть имена ». В качестве бонуса он обеспечивает четкую графику, иллюстрирующую разницу.

    Под обложками вызов по-разному реализуется больше как call-by-reference (как показывает мутате пример float упомянутый Noctis Skytower ). Но если вы думаете об этом как о вызове, вы уйдете с так как в то время как ссылки являются реализацией, они не являются открытой семантикой.

    C #, напротив, использует либо посылку, либо вызов по ссылке – хотя можно утверждать, что опция out представляет собой настройку выше и выше чистого вызова по ссылке, как показано на C, Pascal и т. Д. ,

    Таким образом, Python и C # очень разные – на архитектурном уровне, во всяком случае. На практике комбинация по значению и по ссылке позволит вам создавать программы, которые работают очень похоже на совместное использование звонков, хотя и с сложным маленьким дьяволом, живущим в деталях и в углах.

    Если вы заинтересованы в понимании стратегий передачи параметров разных языков в сравнительном контексте, страница Википедии по стратегии оценки выражений стоит прочитать. Хотя он не является исчерпывающим (существует много способов скинуть этот кот!), Он умело охватывает ряд наиболее важных, а также некоторые интересные необычные варианты.

    Python всегда использует pass по ссылочным значениям. Не исключение. Любое назначение переменной означает присвоение контрольного значения. Никаких исключений. Любая переменная – это имя, привязанное к эталонному значению. Всегда.

    Вы можете думать о ссылке как о адресе целевого объекта, который автоматически разыгрывается при использовании. Таким образом, кажется, вы работаете напрямую с целевым объектом. Но всегда есть ссылка между ними, еще один шаг, чтобы перейти к цели.

    Обновлено – вот нужный пример, который доказывает прохождение по ссылке:

    Иллюстрированный пример передачи аргумента

    Если аргумент передан по значению, внешний 1- lst не может быть изменен. Зеленый – это целевые объекты (черный – это значение, хранящееся внутри, красный – тип объекта), желтый – это память с опорным значением внутри – рисуется как стрелка. Синяя сплошная стрелка – это контрольное значение, которое передается функции (через штрихованный синий путь стрелки). Желтый темно-желтый – это внутренний словарь. (На самом деле его можно было бы нарисовать также как зеленый elipse. Цвет и форма говорят только, что он является внутренним.)

    Обновлено – связано с комментарием fgb о передаче по ссылочному примеру swap(a, b) и комментарию delnan о возможности писать swap .

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

    Целью swap на других языках является обмен содержимым прошедших переменных, т.е. замена содержимого пространств памяти. Это можно сделать и для Python, но только для переменных, которые могут быть изменены – это означает, что содержимое их пространства памяти может быть изменено. Это относится только к изменяемым типам контейнеров. Простая переменная в этом смысле всегда постоянна, хотя ее имя можно повторно использовать для другой цели.

    Если функция должна создать какой-то новый объект, единственный способ получить ее снаружи – это либо через аргумент типа контейнера, либо через команду return Python. Тем не менее, Python return синтаксически выглядеть так, как если бы он мог выходить за пределы более одного аргумента. Фактически, несколько значений, прошедших вне формы, образуют кортеж, но кортеж может быть синтаксически назначен более внешним переменным Python.

    Обновление, связанное с имитацией переменных, поскольку они воспринимаются на других языках. Пространство памяти моделируется одноэлементными списками, то есть еще один уровень косвенности. Затем swap(a, b) может быть записан как на других языках. Странно, что мы должны использовать элемент списка как ссылку на значение моделируемой переменной. Причина, по которой необходимо, чтобы имитировать переменные other-languate, заключается в том, что только контейнеры (их подмножество) являются единственными объектами в Python, которые могут быть изменены:

     >>> def swap(a, b): ... x = a[0] ... a[0] = b[0] ... b[0] = x ... >>> var1 = ['content1'] >>> var2 = ['content2'] >>> var1 ['content1'] >>> var2 ['content2'] >>> id(var1) 35956296L >>> id(var2) 35957064L >>> swap(var1, var2) >>> var1 ['content2'] >>> var2 ['content1'] >>> id(var1) 35956296L >>> id(var2) 35957064L 

    Обратите внимание, что теперь var1 и var2 имитируют внешний вид «обычных» переменных в классических языках. swap изменяет свой контент, но адреса остаются неизменными.

    Для модифицируемого объекта – например, списки – вы можете написать точно такой же swap(a, b) что и на других языках:

     >>> def swap(a, b): ... x = a[:] ... a[:] = b[:] ... b[:] = x[:] ... >>> lst1 = ['a1', 'b1', 'c1'] >>> lst2 = ['a2', 'b2', 'c2'] >>> lst1 ['a1', 'b1', 'c1'] >>> lst2 ['a2', 'b2', 'c2'] >>> id(lst1) 35957320L >>> id(lst2) 35873160L >>> swap(lst1, lst2) >>> lst1 ['a2', 'b2', 'c2'] >>> lst2 ['a1', 'b1', 'c1'] >>> id(lst1) 35957320L >>> id(lst2) 35873160L 

    Обратите внимание, что для выражения копирования содержимого списков необходимо использовать множественное присвоение, такое a[:] = b[:] .

    Python всегда передается по значению:

     def is_python_pass_by_value(foo): foo[0] = 'More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.' foo = ['Python is not pass-by-reference.'] quux = ['Yes, of course, Python *is* pass-by-value!'] is_python_pass_by_value(quux) print(quux[0]) # More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value. 

    По умолчанию C # по умолчанию передается по значению, но также поддерживает передачу по ссылке, если на сайте объявления метода и на сайте вызова используется ключевое слово ref :

     struct MutableCell { public string value; } class Program { static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux) { foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value."; foo = new string[] { "C# is not pass-by-reference." }; bar.value = "For value types, it is *not* call-by-sharing."; bar = new MutableCell { value = "And also not pass-by-reference." }; baz = "It also supports pass-by-reference if explicitly requested."; qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." }; } static void Main(string[] args) { var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" }; var corge = new MutableCell { value = "For value types it is pure pass-by-value." }; var grault = "This string will vanish because of pass-by-reference."; var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." }; IsCSharpPassByValue(quux, corge, ref grault, ref garply); Console.WriteLine(quux[0]); // More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value. Console.WriteLine(corge.value); // For value types it is pure pass-by-value. Console.WriteLine(grault); // It also supports pass-by-reference if explicitly requested. Console.WriteLine(garply.value); // Pass-by-reference is supported for value types as well. } } 

    Как вы можете видеть, без явного аннотации с ключевым словом ref C # ведет себя точно так же, как Python. Типы значений являются передаваемыми по значению, где передаваемое значение является самим объектом, типы Reference являются передаваемыми по значению, где переданное значение является указателем на объект (также называемым совместным использованием «по одному»).

    Python не поддерживает изменяемые типы значений (вероятно, это хорошо), поэтому невозможно наблюдать различие между значениями pass-value-by-value и pass-pointer-by-value, поэтому вы можете просто рассматривать все как pass-pointer- по значению и значительно упростить вашу ментальную модель.

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

    Не совсем так

     def func(a,b): a[0]=5 #Python b=30 

     public int func( ref int a,out int b,int d) { a++;b--; //C# } 

     x=[10] y=20 func(20,30) #python print x,y #Outputs x=[5],y=20 Note:I have used mutable objects.Not possible with int. 

     int x=10,y=20; func(ref x,out y,18); //C# Console.Writeline("x={0} y={1}",x,y);//Outputs x=11,y=19 
    Python - лучший язык программирования в мире.