Equivalents were produced with the Free Edition of C# to Python Converter.
The closest thing in Python to an abstract method is an empty method:
C# | Python |
---|---|
public abstract class AbstractClass { public abstract void abstractMethod(); } |
class AbstractClass: def abstractMethod(self): pass |
You can convert C# arrays to Python's 'list'.
Unsized Array
C# | Python |
---|---|
int[] myArray; | myArray = [] |
Sized Array
C# | Python |
---|---|
int[] myArray = new int[2]; | myArray = [0 for _ in range(2)] |
Access Array Element
C# | Python |
---|---|
x = myArray[0]; | x = myArray[0] # no change |
Jagged Array
C# | Python |
---|---|
float[][] myArray = new float[][] { new float[] {x, y}}; | myArray = [[x, y]] |
Rectangular Array
C# | Python |
---|---|
int[][] myArray = new int[][] { new int[] {10, 20, 30 ,40}, new int[] {50, 60, 70, 80, 90, 100}, new int[] {110, 120} }; |
myArray = [[10, 20, 30, 40], [50, 60, 70, 80, 90, 100], [110, 120]] |
C# requires statements to end with semi-colons and multi-statement blocks to be enclosed in braces, while Python only requires indentation to correspond to the logical block levels and block headers to end in colons. The current instance is only available within instance methods via the first parameter of the method, usually named 'self' by convention (static methods are distinguished by the @staticmethod decorator).
C# | Python |
---|---|
class FooClass { void instanceMethod() { if (fooCondition) { fooLogicOne(); fooLogicTwo(); } } } |
class FooClass: def instanceMethod(self): if fooCondition: fooLogicOne() fooLogicTwo() |
C# | Python |
---|---|
void casts() { x = (int)y; x = (float)y; x = (string)y; } |
def casts(self): x = int(y) x = float(y) x = str(y) |
Lists
C#'s System.Collections.Generic.List collection and Python's 'list' are very close equivalents.
C# | Python |
---|---|
void Lists() { List<int> myList = new List<int>(); myList.Add(1); myList.Insert(1, 2); int i = 1; myList[0] = i; i = myList[0]; } |
def arrayLists(self): myList = [] myList.append(1) myList.insert(1, 2) i = 1 myList[0] = i i = myList[0] |
Dictionaries
C#'s System.Collections.Generic.Dictionary collection and Python's 'dict' are very close equivalents.
C# | Python |
---|---|
void Dictionaries() { Dictionary<string, int> map = new Dictionary<string, int>(); string s = "test"; map[s] = 1; int i = map[s]; i = map.Count; bool b = map.Count == 0; map.Remove(s); } |
def hashMaps(self): map = {} s = "test" map[s] = 1 i = map[s] i = len(map) b = not map map.pop(s) |
Python has a single comment format, starting with the '#' symbol. Multiline comments can also be created using triple quoted multiline strings.
C# | Python |
---|---|
// single-line comment foo(); // end-of-line comment /* comment over multiple lines */ |
# single-line comment foo() # end-of-line comment # comment # over multiple lines # # using multiline strings to simulate multiline comments: """ comment over multiple lines """ |
Local Variable
C# | Python |
---|---|
int myVar = 2; | myVar = 2 # Python infers the type |
Inferred Types
Inferred typing is available in C#, but Python always infers the type:
C# | Python |
---|---|
var myVar = 2; | myVar = 2 |
Static Field
In Python, static fields are initialized at the class level:
C# | Python |
---|---|
class FooClass { public static int staticField = 7; } |
class FooClass: staticField = 7 |
Instance Field
In Python, instance fields are not listed at the class level and are qualified with the instance object, given by the first instance method parameter (usually named 'self' by convention):
C# | Python |
---|---|
class FooClass { public int instanceField = 2; } |
class FooClass: def __init__(self): self.instanceField = 2 |
Local Constant
C# | Python |
---|---|
const int myConst = 2; | MY_CONST = 2 # at method level — up to programmers to respect the naming convention and avoid changing it |
Class Constant
C# | Python |
---|---|
public const int myConst = 2; | MY_CONST = 2 # at class level — up to programmers to respect the naming convention and avoid changing it |
Python constructors are named __init__, but a serious shortcoming of Python is the restriction of allowing only one constructor per class.
C# | Python |
---|---|
class Foo { public Foo() { } } |
class Foo: def __init__(self): pass |
Python and C# both allow default or optional parameters.
C# | Python |
---|---|
public void defaultParam(int param = 0) { ... } |
def defaultParam(self, param=0): ... |
Since methods are first class objects in Python delegates are converted easily:
C# | Python |
---|---|
public class Test { public delegate void FooDelegate(int arg); public static void static_method(int p) { Console.WriteLine("static_method called with arg " + p); } public void instance_method(int p) { Console.WriteLine("instance_method called with arg " + p); } public void method() { FooDelegate f1 = new FooDelegate(static_method); f1(1); FooDelegate f2 = instance_method; f2(2); FooDelegate f3 = (int i) => instance_method(i); f3(3); } } |
class Test: class FooDelegate: def __init__(self, method, instance): self._method = method self._instance = instance def invoke(self, arg): if self._instance is None: self._method(arg) else: self._method(self._instance, arg) @staticmethod def static_method(p): print("static_method called with arg " + str(p)) def instance_method(self, p): print("instance_method called with arg " + str(p)) def method(self): f1 = Test.FooDelegate(Test.static_method, None) f1.invoke(1) f2 = Test.FooDelegate(Test.instance_method, self) f2.invoke(2) f3 = Test.FooDelegate(lambda i : self.instance_method(i), None) f3.invoke(3) |
Enums in C# have equivalents in Python using the 'enum' module:
C# | Python |
---|---|
public enum Simple { Foo, Bar } |
from enum import Enum class Simple(Enum): FOO = 0 BAR = 1 |
......
C# | Python |
---|---|
// value equality with primitives: int i = 1; int j = 1; bool valuesIdentical = i == j; // identity equality with class types: Foo f = new Foo(); Foo g = f; bool objectsIdentical = f == g; // strings: string s1 = "abc"; string s2 = s1; valuesIdentical = s1 == s2; // caution: C# string internment often // makes this true whenever '==' is true: objectsIdentical = string.ReferenceEquals(s1, s2); |
# value equality: i = 1 j = 1 valuesIdentical = i == j # identity equality f = Foo() g = f objectsIdentical = f is g # strings: s1 = "abc" s2 = s1 valuesIdentical = s1 == s2 # caution: Python string internment often # makes this true whenever '==' is true: objectsIdentical = s1 is s2 |
The Python try/except/finally scheme is equivalent to C#'s try/catch/finally:
C# | Python |
---|---|
void exceptionHandling() { try { } catch (Foo f) { throw f; } catch (Bar) { throw new Bar(); } finally { } } |
def exceptionHandling(self): try: pass except Foo as f: raise f except Bar: raise Bar() finally: pass |
Python doesn't have extension methods, so a C# extension method is just converted to an ordinary Python static method (calls to the method have to be adjusted to static calls using the class name).
C# | Python |
---|---|
public static class ContainsExtension { public static void ExtensionMethod(this string myParam) { // ... } } class TestClass { void TestMethod() { string s = "abc"; s.ExtensionMethod(); } } |
class ContainsExtension: @staticmethod def ExtensionMethod(myParam): # ... pass class TestClass: def _TestMethod(self): s = "abc" ContainsExtension.ExtensionMethod(s) |
C# | Python |
---|---|
if (conditionA) { } else if (conditionB) { } else { } |
if conditionA: pass elif conditionB: pass else: pass |
C# allows incrementing and decrementing integers within expressions, while Python doesn't. The following shows how C# to Python Converter handles some cases.
C# | Python |
---|---|
public void incrementDecrement() { i = ++j; i = j++; i = j--; i = s + --t; i = s + t--; i = s + ++t; i = s + t++; } |
def incrementDecrement(self): j += 1 i = j i = j j += 1 i = j j -= 1 t -= 1 i = s + t i = s + t t -= 1 t += 1 i = s + t i = s + t t += 1 |
Python does not have indexers, so you must use get/set methods instead:
C# | Python |
---|---|
public int this[int index] { get { return field[index]; } set { field[index] = value; } } |
def get(self, index): return field[index] def set(self, index, value): field[index] = value |
C# | Python |
---|---|
public class one { protected int baseField = 1; public one(int i) { } public virtual void baseMethod() { } } public class two : one { public two() : base(0) { } public void method() { base.baseField = 2; base.baseMethod(); } } |
class one: def __init__(self, i): self.baseField = 1 def baseMethod(self): pass class two(one): def __init__(self): super().__init__(0) def method(self): self.baseField = 2 super().baseMethod() |
Defining Interfaces
Interfaces in Python are just classes with empty methods:
C# | Python |
---|---|
public interface IFooInterface { void method(); } |
class IFooInterface: def method(self): pass |
Implementing Interfaces
C# | Python |
---|---|
public class Foo : IFooInterface { public void method() { ... some code } } |
class Foo(IFooInterface): def method(self): ... some code |
Expression Lambda
C# | Python |
---|---|
myVar = (String text) => text.Length; | myVar = lambda text : len(text) |
Multi-statement Lambda
C# | Python |
---|---|
myVar = (Foo param1, Bar param2) => { // ...multiple statements } |
No direct Python equivalent |
C# | Python |
---|---|
x = y && z; x = y || z; x = !y; i = j | k; i = j & k; i = j ^ k; |
x = y and z x = y or z x = not y i = j | k i = j & k i = j ^ k |
C# | Python |
---|---|
// while loop: while (while_condition) { foo(); // break and continue: if (b) break; else continue; } // do-while loop: do { foo(); } while (do_condition); // traditional for loop: for (int i = 0; i < 10; i++) { foo(); } // 'for each' loop: foreach (Foo f in FooList) { } |
# while loop: while while_condition: foo() # break and continue: if b: break else: continue # do-while loop: # Python doesn't have a do-while loop, so simulate it: condition = True while condition: foo() condition = do_condition # traditional for loop: for i in range(0, 10): foo() # 'for each' loop: for f in FooList: pass |
C# | Python |
---|---|
void exponentiation() { x = Math.Pow(y, z); } void integerDivision() { // C# integer division always rounds towards 0: int i = -5; int j = 2; int result = i / j; // result is -2 } void modulusOperator() { // C# and Python '%' operators are only equivalent for positive numbers: int i = 2; int j = -3; int result = i % j; // result is 2 } void otherMathOperations() { x = Math.Abs(y); // see the System.Math class for many more functions: x = Math.Cos(y); x = Math.E; x = Math.PI; } |
import math def exponentiation(self): x = y ** z def integerDivision(self): i = -5 j = 2 result = math.trunc(i / float(j)) # result is -2 # Python integer division rounds away from 0 when negative: result = i / j # result is -3 def modulusOperator(self): i = 2 j = -3 result = math.fmod(i, j) # result is 2 # Python modulus operator produces a different result: result = i % j # result is -1 def otherMathOperations(self): x = abs(y) # 'abs' is a built-in Python function # see the Python 'math' module for many more functions: x = math.cos(y) x = math.e x = math.pi |
Python instance methods have a first parameter indicating the instance ('self' is the convention for this parameter and not a keyword), and static methods have the '@staticmethod' decorator.
C# | Python |
---|---|
public void instanceMethod() { } public static void staticMethod() { } |
def instanceMethod(self): pass @staticmethod def staticMethod(): pass |
C# | Python |
---|---|
public class SomeType { private int IntValue = 1; public static int operator +(SomeType X, SomeType Y) { return X.IntValue + Y.IntValue; } public void OperatorTest() { SomeType o = new SomeType(); SomeType p = new SomeType(); i = o + p; } } |
class SomeType: def __init__(self): # instance fields found by C# to Python Converter: self._IntValue = 1 @staticmethod def op_add(X, Y): return X._IntValue + Y._IntValue def OperatorTest(self): o = SomeType() p = SomeType() i = SomeType.op_add(o, p) |
C# | Python |
---|---|
void method(params string[] args) { foreach (string x in args) { ... logic for each item in args } } |
def method(self, *args): for x in args: ... logic for each item in args |
Python does not have properties, so you must use get/set methods instead:
C# | Python |
---|---|
public int IntProperty { get { return intField; } set { intField = value; } } |
def get_int_property(self): return intField def set_int_property(self, value): intField = value |
Python does not support C#-style 'ref' parameters. All Python parameters are passed by value (if it's a reference, then the reference is passed by value). However, you can wrap the parameter type in another type (we call it 'RefObject').
Here's a simple example:
C# | Python |
---|---|
public void refParamMethod(ref int i) { i = 1; } public void callRefParamMethod() { int i = 0; refParamMethod(ref i); } |
def refParamMethod(self, i): i.arg_value = 1 def callRefParamMethod(self): i = 0 temp_ref_i = RefObject(i) self.refParamMethod(temp_ref_i) i = temp_ref_i.arg_value # ---------------------------------------------------------------------------------------- # Copyright © 2022 - 2024 Tangible Software Solutions, Inc. # This class can be used by anyone provided that the copyright notice remains intact. # # This class is used to replicate the ability to have 'ref' parameters in Python. # ---------------------------------------------------------------------------------------- class RefObject: def __init__(self, ref_arg): self.arg_value = ref_arg |
C# static constructors and Python code at the class level serve the same purpose.
C# | Python |
---|---|
class Foo { public static int field; static Foo() { ... logic to set 'field' value } } |
class Foo: field = 0 ... logic to set 'field' value |
C# | Python |
---|---|
String s = initValue; int i = s.IndexOf(y); i = s.LastIndexOf(y); i = s.Length; bool b = s.Contains(y); s = s.Substring(i); s = s.Substring(i, j); b = s.EndsWith(y); b = s.StartsWith(y); s = s.ToLower(); s = s.ToUpper(); s = s.TrimStart(); s = s.TrimEnd(); |
s = initValue i = s.find(y) i = s.rfind(y) i = len(s) b = y in s s = s[i:] s = s[i:i + j] b = s.endswith(y) b = s.startswith(y) s = s.casefold() s = s.upper() s = s.lstrip() s = s.rstrip() |
Python 3.10 has 'match' syntax, but if/elif/else is used prior to Python 3.10.
C# | Python |
---|---|
switch (pivot) { case 1: foo(); break; case 2: case 3: bar(); break; case 4: break; default: ack(); break; } |
Python 3.10: match pivot: case 1: foo() case 2 | 3: bar() case 4: pass case other: ack() Prior to Python 3.10: if pivot == 1: foo() elif pivot == 2 or pivot == 3: bar() elif pivot == 4: pass else: ack() |
C# | Python |
---|---|
result = condition ? truePart : falsePart; | result = truePart if condition else falsePart |
C# | Python |
---|---|
// checking if 'f' is an instance of type 'Foo': bool b = f is Foo; |
# checking if 'f' is an instance of type 'Foo': b = isinstance(f, Foo) |
C# | Python |
---|---|
using FooNamespace; // type import with alias matching type name: using FooClass = FooNamespace.FooClass; // namespace alias: using fooalias = FooNamespace; // type import: using static FooNamespace.BarClass; |
from FooNamespace import * from FooNamespace import FooClass * no equivalent to type or namespace aliases * * no equivalent to C# 'using static' * |
C# | Python |
---|---|
using (FooType foo = new FooType()) { ... } |
with FooType() as foo: ... |
C# | Python |
---|---|
// verbatim string: string s = @"multiline verbatim string"; // C#11 raw string literal: string s = """ multiline verbatim string """; |
s = """multiline verbatim string""" |
Copyright © 2004 – 2024 Tangible Software Solutions, Inc.