Geek Culture
Published in

Geek Culture

Python language through .NET developer eyes

A list of useful code snippets and topics about Python general use scenarios which is worth to remember

If you start learning Python after being a C# developer for quite a long time, you might want to have the same toolset which you had in C#. Here I’d like to give a kind of a mapping from C# to Python, although I should admit it’s not an accurate one. I used moments when I got stuck for some period while developing in Python, as points for this article. It’s worth mentioning that this is not a technical comparison between C# and Python in any regards. So read the article as a fiction which tells you a quick overview of two languages, where they have similar things and where they are different. And the list is not complete for sure.

1. Multiple inheritance in Python

In contrast to C#, Python has multiple inheritance, similar to C++. Personally, I don’t see much use of the multiple inheritance and I even recommend avoiding it for the sake of code clarity. But if you decide to use it, bear in mind the “diamond problem” related to such kind of inheritance. As to Python, they have a clear method resolution order (MRO).

class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>

The only rule necessary to explain the semantics is the resolution rule used for class attribute references. This is depth-first, left-to-right. Thus, if an attribute is not found in DerivedClassName, it is searched in Base1, then (recursively) in the base classes of Base1, and only if it is not found there, it is searched in Base2, and so on.

And some more advanced examples:

2. Python Lambdas

Lambdas in C# and Python stand for anonymous functions. Having a bit different syntax, you can do the same things with them, including passing as a parameter to another function and using in closures. This is how they look in C#:

var a = 3;
Func<int, int> f1 = x => a + x;
Func<double, Func<int, int>, double> f2 = (y, f) => y / f((int)y);
var result = f2(5, f1);
Console.WriteLine($"result: {result}"); # output "result: 0.625"

and in Python:

a = 3
f1 = lambda x: a + x
f2 = lambda x, f: x / f(x)
result = f2(5, f1)
print("result:", result) # output "result: 0.625"

If lambda doesn’t have arguments, they just omitted:

f = lambda: 5
f() # returns 5

3. Closures

Python and C# has closures. There is no big difference in their usage, except different syntax.

C# closure:

Func<int, Action> create_closure = delegate(int a){
Action f = () => Console.WriteLine($"this is: {a}");
return f;
};
var f1 = create_closure(1);
var f2 = create_closure(2);
f1();
f2();

Python closure:

def create_closure(a):

def f():
print("this is:", a)

return f

f1 = create_closure(1)
f2 = create_closure("text")
f1()
f2()

4. Partial Functions

There is no anything like this in C#. But if you know C++ it will be familiar. Let me give you a small example:

from functools import partialdef f1(a,b,c):
return 100*a+10*b+c

f2 = partial(f1, b=5, c=2)
print(f2(3))

The function f2 is a partial one. You may notice that it’s a kind of a wrapper around the function f1 with hardcoded values of two other parameters. In C# we can achieve similar functionality with writing additional functions which call another.

Func<int, int, int, int> f1 = (a, b, c) => 100 * a + 10 * b + c;
Func<int, int> f2 = (a) => f1(a, 5, 2);
Console.WriteLine($"{f2(3)}");

5. Comprehension in Python

When you write a code in C# which needs to iterate through items of some set (list, array, dictionary), you would think of that task in the category of a loop-operator. This is what you need to know from the beginning of learning Python: it has a more performant way of doing such tasks. It’s called list comprehension or dictionary comprehension.

Let me give you an example of a simple task: filtering of an array. In C# it would look something like this:

var a = new [] {1, 2, 3, 4, 5, 6, 7, 8, 9};
var result = new List<int>();
foreach (var item in a){
if (item % 2 == 0){
result.Add(item);
}
}
foreach(var item in result){
Console.Write($"{item}, ");
}

We can optimize this code in C# by using Linq, but under the hood it still will be a loop-operator.

var a = new [] {1, 2, 3, 4, 5, 6, 7, 8, 9};
var result = a.Where(item => item % 2 == 0);
foreach(var item in result){
Console.Write($"{item}, ");
}

For the case with Python I want to give an example of both options together with a performance check which you can try in online Python editor. The version with comprehension is always a bit faster.

import timeita = range(10000)  # a big listdef filtering_using_comprehension():
result = [i for i in a if i%2==0]

def filtering_using_loop():
result2 = []
for i in a:
if i%2==0:
result2 += [i]

n = 100
print("avg.time:", timeit.timeit(filtering_using_comprehension, number=n)/n*1000,"ms")
print("avg.time:", timeit.timeit(filtering_using_loop, number=n)/n*1000,"ms")
output:
avg.time: 0.7362717300020449 ms
avg.time: 1.1933808300091187 ms

The comprehension technique becomes in handy when you work with dictionaries. Here is a simple code to calculate character count in a random text using map-reduce technique and dictionary comprehension:

from functools import reduceinput_text = "aabcccbaabc"c = [(c, 1) for c in input_text]
d = {c: 0 for c in input_text}
r = {k: reduce(lambda x, y: x+y, [i[1] for i in list(filter(lambda x: x[0]==k, c))]) for k in d}
print(r)
output:
{'a': 4, 'b': 3, 'c': 4}

6. Measuring time length of a function execution

There are two ways of doing this which I know. One is similar to what we usually do in C# via Stopwatch class. In Python there is a Timer class with similar usage.

Another way is using a module which specifically developed for such measurements and profiling: timeit.

7. Loop operator can have Else section in Python

In cases when you need to know if a loop operator quitted earlier than all item where checked, the Else section comes in handy. In C# we don’t have anything like that and doing such checks introduces additional flags.

The Else section is executed when a loop statement completes normally. If your code encounters break or return operator, it won’t be executed.

8. Chaining comparison operators in Python

Just worth to know such syntax is possible in Python: a < b < c.

9. Packing and Unpacking arguments, *args, **kwargs

In C# we can use params keyword to specify that a method takes a variable number of arguments. We also can use named arguments with default values to make their usage optional.

Python has more flexible syntax to achieve similar behavior. In Python, when a method receives a finite number of arguments, you can unpack an array to pass its values as values of method arguments.

def f1(a, b, c, d):
print(a,b,c,d) # single values: 1 2 3 9
a=[1,2,3]
f1(*a,9)

If a method receives a variable number of arguments (the exact case of usage params in C#), you can pack positional arguments.

def f2(*args):
print(args) # a tuple: (1, 2, 't')
print(args[1]) # output: 2

f2(1,2,"t")

In contrast to C#, Python can pack named arguments.

def f3(**kwargs):
print(kwargs) # a dictionary: {'a': 1, 'value': 2, 'name': 't'}
print(kwargs["name"]) # output: t

f3(a=1,value=2,name="t")

10. Generator functions in Python

There is a feature in C# which comes in handy when you work with large data (larger than your RAM can allocate) or with repetitive web requests and when you need to process every result as soon as your code acquires control of it. The operator yield return, in conjunction with IEnumerable<T>, allows to do this and a simple example would look as follows:

public static IEnumerable<int> Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}

In Python such functions are called generators. In contrast to C# such functions use only yield, it replaces return operators.

def power(number, exponent):
result = 1
i = range(exponent)
for n in i:
result = result * number
yield result

11. Async/Await in Python and run async code from non-async

This is the first question which comes up when you start working with IO-bound operations in Python (databases, API etc.). IMO an example is better than words, so below is a simple code, which starts several parallel tasks and then awaits all of them to complete.

import asyncio
from time import time
def run_async(async_func):
loop = asyncio.get_event_loop()
result = loop.run_until_complete(async_func)
return result
async def delay(sleep):
print(f'before: {sleep}')
await asyncio.sleep(sleep)
print(f'after: {sleep}')
async def parallel_tasks_with_await_all():
tasks = []
task = asyncio.create_task(delay(2))
tasks.append(task)
task = asyncio.create_task(delay(5))
tasks.append(task)
task = asyncio.create_task(delay(3))
tasks.append(task)
await asyncio.gather(*tasks, return_exceptions=True)
async def sync_block():
await delay(2)
await delay(5)
await delay(3)
print("ready")
start = time()
run_async(parallel_tasks_with_await_all())
print(f"Executed for {time()-start} secs")
print("finish")
The output:
ready
before: 2
before: 5
before: 3
after: 2
after: 3
after: 5
Executed for 5.002882242202759 secs
finish

This example shows several features:

  • The method run_async is an example of calling an async function within a non-async context. In Python it may be useful because some tools and frameworks (like Airfow) do not use async/await, but at the same time you want to write your libraries which can benefit from async code.
  • The method parallel_tasks_with_await_all shows how to start several tasks and then await all of them together (similar to Task.WaitAll in C#).
  • The method sync_block shows non-blocking execution of methods in a synchronous manner.

You can check that Python executes tasks in parallel by calling the method sync_block instead of parallel_tasks_with_await_all:

old: run_async(parallel_tasks_with_await_all())new: run_async(sync_block())The output:
ready
before: 2
after: 2
before: 5
after: 5
before: 3
after: 3
Executed for 10.010915279388428 secs
finish

It’s also possible to control the number of tasks executed in parallel. Python module asyncio has an implementation of Semaphore. The following snippet shows how to use it to limit number of tasks:

async def gather_with_concurrency(n, *tasks):
semaphore = asyncio.Semaphore(n)

async def sem_task(task):
async with semaphore:
return await task
return await asyncio.gather(*(sem_task(task) for task in tasks))

--

--

--

A new tech publication by Start it up (https://medium.com/swlh).

Recommended from Medium

Using animation in Flutter

Federated Applications: E Plurbus Unum

Java 15 new features

🔰Kubernetes: Revolutionizing Industries🔰

Managing performance for small and middle-sized web application

Pair Programming

iOS: Implementing the Protocol/Delegate Communication Pattern

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alexander Goida

Alexander Goida

All opinions are my own || Software Developer, learner, perfectionist and entrepreneur-kind person, nonconformist. Always seeks for the order and completeness.

More from Medium

How To Do Math In Python Using Operators

Translating Languages Using Python

What are environment variables and how to manage them in Python?

Philips Hue with python

Python philips hue