dgplug member blogs


Read the latest posts from dgplug member blogs.

from mrinalraj


Folks! Have you ever wondered how to create a URL that always points to your router, even when its public IP address changes? It might sound complex and costly, but it's actually free!


This involves setting up Dynamic DNS (DDNS).

What you need

  1. A Wi-Fi Router supporting NO-IP as DDNS
  2. An account on NO-IP website

Steps for creating hostname in NO IP:

  1. Login to NO-IP website. Make sure to avoid use of special character in the password.
  2. Create a hostname.
  3. We are Done!!!

Steps for configuring DDNS in router:

  1. Login to your router with credentials.
  2. Navigate to DDNS which would possibly under Internet tab.
  3. Configuring DDNS. 3.1 Keep WAN Connection as 'auto'. 3.2 Provider: 'No-IP' 3.3 Username: 3.4 Password: 3.5 Hostname: Give the newly created hostname
  4. We are Done!!!


Reboot your router and verify if NO IP website is showing the recent router's public IP.


Now every time your router public IP changes it would reflect the recent IP on the website.


NO-IP provides a free DDNS hostname that can be used in projects instead of the router's public IP address. Simply confirm the renewal email after 30 days.

Thank you !!! Follow Mrinal


from mrinalraj


Imagine wanting to stream video from a device behind your home router to your personal phone over the internet. This may sound like a complex task, but with port forwarding, it's simpler than you think.

What you need:

  1. A Wi-Fi Router
  2. A computer displaying the video feed connected to the Wi-Fi router
  3. A VNC viewer on your remote mobile device

The Solution:

Port forwarding is the secret sauce that makes this setup seamless. Here's how you can do it:


Router –> Computer –> Display | Internet –> Mobile –> VNC

  1. Lets Visualize the network diagram as above.
  2. Be physically near your router.
  3. Login your Wi-Fi router with credentials.
  4. Navigate to Port Forwarding section. It must be in the Security section.
  5. Set the Port forwarding rules 5.1. Service Name: Give the port forwarding rule a descriptive name. 5.2. Port Range: Specify the range of ports you want to forward (e.g., 5900- 5901 for a single port). 5.3. Local IP Address: Enter the IP address of the device on your local network that you want to forward the ports to. Refer my previous post on How to make a connected device static. 5.4. Protocol: Select the protocol for the port forwarding rule (TCP, UDP, or both). 5.5 Keep WAN HOST IP as

We are done here!!! See its that simple. Lets now test it over is my port open? website.

On Personal Mobile over Internet

  1. Install VNC over mobile phone
  2. Enter the router public IP followed by port number eg.
  3. Suppose you don't have a router public IP address handy you can get it from what's my IP address? website.
  4. Above IP means that in the router public IP, connect to device at port 5900
  5. Enter credentials and we are done!!!


  1. Since your router IP changes after reboot. Refer my previous post on How to get free url for Router's public IPs
  2. If the local device streaming feed is not static. It me loose the IP after device restart. Making device static is better solution. Refer my previous post on How to make a connected device static.

Thank you !!! Follow Mrinal


from mrinalraj


I recently needed to establish a static IP for my Python project to facilitate SSH access. The issue I faced was that DHCP kept assigning a new IP every time my system rebooted.

I discovered that we can set the IP address to be static, and the steps for doing so are outlined below:

Step 1: Open the dhcpcd.conf file

sudo nano /etc/dhcpcd.conf

If your project uses Wi-Fi, proceed with the following steps; otherwise, replace the interface name accordingly. interface wlan0 static ip_address=your_desired_static_ip/24 static routers=your_router_ip static domain_name_servers=your_dns_server_ip

Replace “your_desired_static_ip”, “your_router_ip”, and “your_dns_server_ip” with the appropriate values for your network. Ensure you choose an IP address that is not already in use on your network.

Step 2: Restart the dhcp service

sudo service dhcpcd restart or do sudo reboot


from mrinalraj


I recently wanted my Python program to execute right after the system boots up. I discovered several options to achieve this, eliminating the need for manual intervention to run the program.

Option 1: Editing through Crontab

  1. Open a terminal with elevated privileges: sudo su -
  2. Edit the crontab configuration: crontab -e
  3. Add the following command to start the Python program (assuming you want to run it on a Raspberry Pi terminal): ```bash
  4. @reboot /usr/bin/python3 /path/to/your/script.py

Option 2: Editing through services using systemd

  • Create a script, name it as “myscript.sh”
  • Make the script executable: chmod +x myscript.sh
  • Navigate to the systemd directory: cd /etc/systemd/system/
  • Create a service file named “myscript.service” inside the systemd directory.
  • And below lines using nano myscript.sh
Description=My Script


  • Reload systemd: sudo systemctl daemon-reload
  • Enable the service: sudo systemctl enable myscript.service
  • Start the service: sudo systemctl start myscript.service
  • To check the service status: sudo systemctl status myscript.service

Option 3: Autostart using lxsession

  • Edit the autostart configuration file: nano ~/.config/lxsession/LXDE-pi/autostart
  • Add the following line to automatically start the Python script: @lxterminal -e python3 /path/to/your/script.py
  • Save the file and initiate a system reboot: sudo reboot

from Pradhvan


Week 1 started with a welcome session hosted by the organizers to give us all an opportunity to say hello and meet each other. Since most of the folks would be working in different teams, it was really nice to talk to each member of the cohort in one session.

WelcomeToDjangonautSpace Djangonaut Welcome Session

I picked up two issues to work on this week:

  • For djangoproject.com, I am working on fixing feed aggregation that let's approved users add their RSS feed in the website. The github issue #1137 has a fair bit of information on the issue and the detailed notes from Carlton were really helpful to get a mental model of the problem. I am still working on a draft PR and hopefully I can have a initial version of the draft out for review in the next week or so.

  • For django-cms, I am pairing with my fellow team mates on the issue #5839 that deals with Internationalization and redirection of a page and homepage when the pages have content in different languages. On our pairing session we did manage to replicate the same issue in django-cms quickstart but weren't able to figure it out, need to do some more digging on it.

What I learnt this week 🧠

  • Supporting Multiple Languages with Django
  • How to set single instance model with constraints in Django
  • How to configure multiple pages with primary and fallback languages in django-cms

Side Quests 🧙🏾‍♂️

  • For django-cms I think a really good tutorial can be one that builds upon where Django Girls tutorial leaves you with. This tutorial can also serve really well as getting started guide for django-cms from a perspective of someone who isn't well versed with Django or wants a beginner friendly introduction on how to use django-cms with your Django project.


  • I need to set more structured and dedicated time to work on the issues I pick up during the week.

Credits: – Djangonaut Logo



from Pradhvan


2024 has started on a good note for me, I got accepted into the the djangonaut program. It's a eight week mentorship program run by folks in the Django community to help others contribute back to the Django ecosystem.

Team size is intentionally kept small, for three Djangonauts per team there is one captian and one navigator.

Week 0 is mostly focused on getting to know folks in the cohort, your team and the mentors.

I got sorted into a team mars and we're working on contributions to the django-cms project.

The team consists of me, Moe, Raffaella, Anvansh our captian and Mark Walker as our navigator.

Activity Log for Week 0:

  • Picked a weekly catchup time with Mark, since all of us are on a different timezone.
  • Joined the django-cms's slack channel and got introduced to other memeber of the community in the django-cms's bi-weekly tech committee meeting.
  • Played with django-cms-quickstart to get a bird eye's view of the project.
  • Picked out potential tickets to work on for next week.

One really cool thing I liked about the cohort is they're big on encouraging us to talk with other members on the discord channel, explore various team projects, and pick up tasks that interest us from them.

I've always been fascinated by Django Debug Toolbar and ORM, so I'm thinking of starting with some low-hanging fruit there or revisiting my old Django tickets that I left hanging.

Looking forward to the next eight weeks to collaborate with this amazing community and learn along the way.

Credits: – Djangonaut Logo



from mrinalraj

धर्मो रक्षति रक्षितः जो लोग ’धर्म’ की रक्षा करते हैं, उनकी रक्षा स्वयं हो जाती है। means the Dharma protects those who protect it. Here, Dharma means the righteous path.

The entire Ramayana carved out of a mountainside, Ellora Caves, India

Namaskaram, look at the India that is Bharat, proudly standing with its ancient civilization.

What is going on in Bharat?

You see, from ancient times, we have been celebrating Diwali around November by lighting up with Diyas to welcome the arrival of Lord Vishnu's twenty-fourth incarnation, Maryada Purushottam Shri Ram. So, lighting up with diyas is to showcase the arrival of the path for Prabhu Shree Ram after mankind's victory over evil, thereby establishing Dharma(that is, the righteous path). This is different from the traditional Deepawali celebration.

But how this Jan 22nd is different?

You see after the historical judgment passed by the Supreme Court of India in 2019, which started in 1986 that is after 37 years long legal battle and 500 years wait, Lord Ram's child incarnation will be established in his birthplace, Ayodhya by January 22, 2024. It symbolizes the return of Shri Ram back to his birthplace. This January 22nd, a highly knowledgeable saint will perform Pran Pratishthanam.

So now, what does Pran Pratishthanam mean?

Pran Pratishthanam means to connect with the godly vibe of the Maryada Purushottam Shri Ram and to breathe life into the shaligram stone which arrived from Nepal, so again the Ayodhya diplomacy comes into the picture.

The Uncertainty and Turbulence of 500 Years.

What was uncertainty and Turbulence? Though there was uncertainty and turbulence for 500 years after the destruction, the people of Bharat/World didn't lose hope and continued their contribution with labor/money/by sending granite stones from various places which would be later utilized for the reconstruction of the holy place.

Ram Rajya and Ayodhya Diplomacy

Continuing with the above point I am making; the entire people of India & the World are contributing by some means and are feeling connected to the land of Ayodhya. * Mauritus announced 2 hours leave. * Nepal sending more than 3000 gifts. and many more incoming.


Rejuvenation of the ancient civilization sometimes helps us understand ourselves. When the path in front of us seems blurry then it acts as the guiding principle for us to continue the path of Dharma (this is the correct path)


Follow Mrinal


from sandeepk

In CSS, combinators are used to select content by combining selectors in specific relationships. There are different types of relationships that can be used to combine selectors.

Descendant combinator

The descendant combinator is represented by a space “ ” and typically used between two selectors. It selects the second selector if the first selector is the ancestor (parent, parent parent's) element. These selectors are called the descendant selectors.

.cover p {
    color: red;
<div class="cover"><p>Text in .cover</p></div>
<p>Text not in .cover</p>

In this example, the text “Text in .cover” will be displayed in red.

Child combinators

The child combinator is represented by “>” and is used between two selectors. In this, an element is only selected if the second selector is the direct child of the first selector element. This means there should not be any other selector between the first selector element and second element selector.

ul > li {
    border-top: 5px solid red;
    <li>Unordered item</li>
    <li>Unordered item
            <li>Item 1</li>
            <li>Item 2</li>

In this example, the <li> element with the text “Unordered item” will have a red top border.

Adjacent sibling combinator

The adjacent sibling combinator is represented by “+” is placed between the two CSS selector. In this element is selected if the selector element is directly followed by the first element selector or only the adjacent sibling

h1 + span {
    font-weight: bold;
    background-color: #333;
    color: #fff;
    padding: .5em;
    <h1>A heading</h1>
    <span>Veggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon amaranth tatsoi tomatillo
            melon azuki bean garlic.</span>

    <span>Gumbo beet greens corn soko endive gumbo gourd. Parsley shallot courgette tatsoi pea sprouts fava bean collard
            greens dandelion okra wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.</span>

In this example, the first element will have the given CSS properties.

General sibling combinator

The general sibling combinator is represented by “~“. It selects all the sibling element, not only the direct sibling element, then we use the general sibling combinator.

h1 ~ h2 {
    font-weight: bold;
    background-color: #333;
    color: #fff;
    padding: .5em;
    <h1>A heading</h1>
    <h2>I am a paragraph.</h2>
    <div>I am a div</div>
    <h2>I am another paragraph.</h2>

In this example, every <h2> element will have the given CSS properties.

CSS combinators provide powerful ways to select and style content based on their relationships in the HTML structure. By understanding combinators, we can create clean, maintainable, and responsive web designs.


ReferencesMDN Web Docs

#CSS #Combinators #WebDevelopment #FrontendDev


from Pradhvan

Python has a built in function called abs() that is used to find the absolute value from an interget or float value.

Absolute values are values that return a magnitue of a given number. If I put it in more simple tems, magnitue of a number tells us how far they are from zero in the number line.

For negative numbers - sign is not considered.


>>> x, y = -10.11, -10
>>> abs(x)

Like most of python builtins it also has a dunder method __abs__

>>> y = -10
>>> y.__abs__()
>>> 10

Real World Example


Suppose you are given a chart of temprature that has temprature values and you need to find the value that is closest to 0.

class TempratureReader:

    def closest_to_zero(self, readings: List[float]) -> float:

        result = readings[0]

        for reading in readings:
            if abs(reading) < abs(result):
                result = reading
            elif abs(reading) == abs(result):
                result = max(result, reading )

        return result
>>> t = TempratureReader()
>>> t.closest_to_zero([10.11,-35.11,22.11, -2.1, -1.1, 1.1])
>>> 1.1

absoulte values of other types

  • For complex number, abs() returns the maginitudu.
>>> num = complex(3, 10)
>>> num
>>> (3+10j)
>>> abs(num)
>>> 10.44030650891055
  • For Decimal values it just works like float just returns the postive value.



from sandeepk

Today, I decided to analyze my bank account statement by downloading it from the day I opened my bank account. To my surprise, it was presented as a web page. Initially, my inner developer urged me to write code to scrape that data. However, feeling a bit lazy, I postponed doing so.

Later in the evening, I searched the web to find an alternate way to extract the data and discovered that HTML tables can be converted to CSV files. All I had to do was save the code in CSV format. I opened the Chrome browser's inspect code feature, copied the table, saved it with the CSV extension, and then opened the file with LibreOffice. Voila! I had the spreadsheet with all my transactions.




from Pradhvan

How not to do it

If you are doing a fresh setup of UFW whenever you add a rule like ufw allow 'Nginx HTTP' the status of it would be inactive.

$sudo ufw allow 'Nginx HTTP'
Rule added
$sudo ufw status
Status: inactive

This would seem odd right, why is it inactive.

During your search, you may discover that you need to activate it with a new command that you find on the internet in order to understand why it was inactive. So you just enable it.

Simple problem, simple solution. :-P

$sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

If you just do yes here and go on a break closing the ssh connection.

Congratulations, you are logged out of your server.


This just happened with me today while setting up a small droplet on digitalocean that hosts static page for a domain with nginx.

How to do it correctly

The problem lies in the last command

$sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

There can be three cases now if you have enabled UFW.

First, don't quit the ssh session and add a rule to allow ssh connection.

$sudo ufw allow OpenSSH
$sudo ufw allow ssh
$sudo ufw allow 22

Assuming you use a default port for ssh, if it;s some other port you can just allow that port number like the port 333

$sudo ufw allow 333

That way you would still have access to SSH when your session ends/timesout.

Second, be smart and allow ssh ports before you enable the ufw.

Third, you just go bonkers and reset the ufw and start again. hahahaha!

sudo ufw reset

Common ufw commands you might find handy

  • Be sus and deny incoming.
# Set the defaults to deny incoming and allow outgoing connections
$sudo ufw default deny incoming
$sudo ufw default allow outgoing

  • Allow specific port ranges
$sudo ufw allow 6000:6007/tcp
$sudo ufw allow 6000:6007/udp
  • Allow specific address
$sudo ufw allow from



from Pradhvan

Decorators 101

  • A decorator may perform some processing with the decorated function, and returns it or replaces it with another function or callable object.

  • Inspection reveals that target is a now a reference to inner

def target():
    print("Running target()")

target # <function deco.<locals>.inner at 0x10063b598>
  • Decorators have the power to replace the decorated function with a different one.
  • Decorators are executed immediately when a module is loaded.
# Program to check how decorators are executed

registry = []

def register(func):
    print(f"running register({func})")
    return func

def f1():
    print("running f1()")

def f2():
    print("running f2()")

def f3():
    print(f"running f3()")

def main():
    print("running main()")
    print("registry ->", registry)

if __name__ == '__main__':

running register(<function f1 at 0x107a25c10>)
running register(<function f2 at 0x1079b0280>)
running main()
registry -> [<function f1 at 0x107a25c10>, <function f2 at 0x1079b0280>]
running f1()
running f2()
running f3()

  • Register runs (twice) before any other function in the module.

  • When register is called, it receives as an argument the function object being decorated—for example, <function f1 at 0x100631bf8>.

    • After the module is loaded, the registry list holds references to the two decorated functions: f1 and f2.
  • A real decorator is usually defined in one module and applied to functions in other modules.Unlike the example above.

Variable Scoping

b = 6

def smart_function(a):
    b = 9 



      3 def smart_function(a):
      4     print(a)
----> 5     print(b)
      6     b = 9

UnboundLocalError: local variable 'b' referenced before assignment
  • Python does not require you to declare variables, but assumes that a variable assigned in the body of a function is local.

  • To make the above program work with b=6 you would need to use the keyword global.


  • A closure is a function with an extended scope that encompasses nonglobal variables referenced in the body of the function but not defined there.

  • It does not matter whether the function is anonymous or not; what matters is that it can access nonglobal variables that are defined outside of its body.

# Closure Example

def make_averager():
    series = [] # Free Variable
    def averager(new_value):
        total = sum(series)
        return total/sum(series)
    return averager # Returns a function object

avg = make_averager()

avg(10) # 10.0

avg(11) # 10.5 

avg(12) # 1.0
  • series is a local variable of make_averager because the assignment series = [] happens in the body of that function. But when avg(10) is called, make_averager has already returned, and its local scope is long gone.

  • Within averager(), series is a free variable i.e a variable that is not bound in the local scope.

  • __code__ attribute keeps the names of the local and free variables.

  • The value for series is kept in the __closure__ attribute of the returned function avg.

avg.__code__.co_varnames # ('new_value', 'total')

avg.__code__.co_freevars # ('series',)

avg.__closure__ # (<cell at 0x107a44f78: list object at 0x107a91a48>,) 

avg.__closure__[0].cell_contents # [10, 11, 12]

Formal Definition

A closure is a function that retains the bindings of the free variables that exist when the function is defined, so that they can be used later when the function is invoked and the defining scope is no longer available.

Refactoring averager

def make_averager():
    count = 0
    total = 0
    def averager(new_value):
        count += 1
        total += new_value
        return total/count
    return averager

avg = make_averager()

UnboundLocalError: local variable 'count' referenced before assignment

Why did count not behave like series i.e free variable ?

  • For series we took advantage of the fact that lists are mutable and we never assigned to the series name. We only called series.append and invoked sum and len on it.
  • count is an immutable types and all you can do is read, never update. If you try to rebind them, as in count = count + 1, then you are implicitly creating a local variable count. It is no longer a free variable, and therefore it is not saved in the closure.

Refactoring averager with nonlocal

def make_averager():
    count = 0
    total = 0
    def average(new_value):
        nonlocal count, total
        count += 1 
        total += new_value
        return total / count 
    return averager
  • nonlocal lets you declare a variable as a free variable even when it is assigned within the function.
  • If a new value is assigned to a nonlocal variable, the binding stored in the closure is changed.

    # Code example here!

Understanding a simple decorator

# clockdeco.py
import time 

def clock(func):
    def clocked(*args):
        t0 = time.perf_counter()
        # closure for clocked encompasses the func free variable
        result = func(*args)
        elapsed = time.perf_counter()
        name = func.__name__
        arg_str = ','.join(repr(args) for arg in args)
        print(f'[{elapsed:0.8f}s] {name}({arg_str}) -> {result!r}')
        return result
    return clocked
# SimpleDeco.py

import time 

from clockdeco import clock

def snooze(seconds):

def factorial(n):
    return 1 if n < 2 else n*factorial(n-1)

if __name__ == '__main__':
    print('*' * 40, 'Calling snooze(.123)')
    print('*' * 40, 'Calling factorial(6)')
    print('6! =', factorial(6))

**************************************** Calling snooze(.123)
[14549.25258126s] snooze((0.123,)) -> None
**************************************** Calling factorial(6)
[14549.25291446s] factorial((1,)) -> 1
[14549.25296426s] factorial((2,)) -> 2
[14549.25301028s] factorial((3,)) -> 6
[14549.25305792s] factorial((4,)) -> 24
[14549.25310024s] factorial((5,)) -> 120
[14549.25314435s] factorial((6,)) -> 720
6! = 720
  • @clock on factorial(n) is just the syntatic sugar for factorial = clock(factorial)
  • clock(func) gets the factorial function as its func argument.
  • It then creates and returns the clocked function, which the Python interpreter assigns to factorial behind the scenes.
  • The __name__ of factorial(n) would give you clocked
import clockdeco_demo
  • Each time factorial(n) is called, clocked(n) gets executed.

Common Decorators in the standard library through functools

  • @wraps
  • @lru_cache
  • @singledispatch

#notes #Python #FluentPython #Decorators #Closure


from sandeepk

The Debug Diary – Chapter I

Lately, I was debugging an issue with the importer tasks of our codebase and came across a code block which looks fine but makes an extra database query in the loop. When you have a look at the Django ORM query

jato_vehicles = JatoVehicle.objects.filter(
).only("manufacturer_code", "uid", "year", "model", "trim")

for entry in jato_vehicles.iterator():
    if entry.manufacturer_code:
    ymt_key = (entry.year, entry.model, entry.trim_processed)

you will notice we are using only, which only loads the set of fields mentioned and deferred other fields, but in the loop, we are using the field trim_processed which is a deferred field and will result in an extra database call.

Now, as we have identified the performance issue, the best way to handle the cases like this is to use values or values_list. The use of only should be discouraged in the cases like these.

Update code will look like this

jato_vehicles = JatoVehicle.objects.filter(

for entry in jato_vehicles.iterator():
    if entry.manufacturer_code:
    ymt_key = (entry.year, entry.model, entry.trim_processed)

By doing this, we are safe from accessing the fields which are not mentioned in the values_list. If anyone tries to do so, an exception will be raised.

** By using named=True we get the result as a named tuple which makes it easy to access the values :)


#Django #ORM #Debug


from sandeepk

select_for_update is the answer if you want to acquire a lock on the row. The lock is only released after the transaction is completed. This is similar to the Select for update statement in the SQL query.

>>> Dealership.objects.select_for_update().get(pk='iamid')
>>> # Here lock is only required on Dealership object
>>> Dealership.objects.select_related('oem').select_for_update(of=('self',))

select_for_update have these four arguments with these default value – nowait=False – skiplocked=False – of=() – nokey=False

Let's see what these all arguments mean


Think of the scenario where the lock is already acquired by another query, in this case, you want your query to wait or raise an error, This behavior can be controlled by nowait, If nowait=True we will raise the DatabaseError otherwise it will wait for the lock to be released.


As somewhat name implies, it helps to decide whether to consider a locked row in the evaluated query. If the skip_locked=true locked rows will not be considered.

nowait and skip_locked are mutually exclusive using both together will raise ValueError


In select_for_update when the query is evaluated, the lock is also acquired on the select related rows as in the query. If one doesn't wish the same, they can use of where they can specify fields to acquire a lock on

>>> Dealership.objects.select_related('oem').select_for_update(of=('self',))
# Just be sure we don't have any nullable relation with OEM


This helps you to create a weak lock. This means the other query can create new rows which refer to the locked rows (any reference relationship).

Few more important points to keep in mind select_for_update doesn't allow nullable relations, you have to explicitly exclude these nullable conditions. In auto-commit mode, select_for_update fails with error TransactionManagementError you have to add code in a transaction explicitly. I have struggled around these points :).

Here is all about select_for_update which you require to know to use in your code and to do changes to your database.


#Python #Django #ORM #Database


from sandeepk

Today, we are going to see how we can use | operator in our python code to achieve clean code.

Here is the code where we have used map and filter for a specific operation.

In [1]: arr = [11, 12, 14, 15, 18]
In [2]: list(map(lambda x: x * 2, filter(lambda x: x%2 ==1, arr)))
Out[2]: [22, 30]

The same code with Pipes.

In [1]: from pipe import select, where
In [2]: arr = [11, 12, 14, 15, 18]
In [3]: list(arr | where (lambda x: x%2 ==1) | select(lambda x:x *2))
Out[3]: [22, 30]

Pipes passes the result of one function to another function, have inbuilt pipes method like select, where, tee, traverse.

Install Pipe

>> pip install pipe


Recursively unfold iterable:

In [12]: arr = [[1,2,3], [3,4,[56]]]
In [13]: list(arr | traverse)
Out[13]: [1, 2, 3, 3, 4, 56]


An alias for map().

In [1]: arr = [11, 12, 14, 15, 18]
In [2]: list(filter(lambda x: x%2 ==1, arr))
Out[2]: [11, 15]


Only yields the matching items of the given iterable:

In [1]: arr = [11, 12, 14, 15, 18]
In [2]: list(arr | where(lambda x: x % 2 == 0))
Out[2]: [12, 14, 18]


Like Python's built-in “sorted” primitive. Allows cmp (Python 2.x only), key, and reverse arguments. By default, sorts using the identity function as the key.

In [1]:  ''.join("python" | sort)
Out[1]:  'hnopty'


Like Python's built-in “reversed” primitive.

In [1]:  list([1, 2, 3] | reverse)
Out[1]:   [3, 2, 1]


Like Python's strip-method for str.

In [1]:  '  abc   ' | strip
Out[1]:  'abc'

That's all for today, In this blog you have seen how to install the Pipe and use the Pipe to write clean and short code using inbuilt pipes, you can check more over here


#100DaysToOffload #Python #DGPLUG


from abbisk


Variable is a way to refer to memory locations being accessed by a computer program. In languages like C, C++, Java, a variable is a name given to a memory location. So when we say:

int x;
float y;

This small piece of code asks the compiler to create memory space for the variables, 4 bytes each (the size depends on the compiler and programming language). The variables are basically names assigned to the memory location, if the variable is defined for a particular data type then only declared type data can be stored in it. But in python, we do not need to declare a variable beforehand like int x, we can straightaway move to define the variable and start using it like x = 10. alt text

Now the point is, how does Python know what is the type of the variable and how to access it? In Python, data types (integer, list, string, functions, etc. ) are objects and every object has a unique id that is assigned to it, at the time of object creation. Variables are references (pointers) to these objects. What happens when we say :

x = 10
  • Python executes the right-hand side of the code
  • Identifies 10 to be an integer
  • Creates an object of Integer class
  • Assigns x to refer to the integer object 10 alt text

Now if we create new variable y which is equal to x, what do you think happens internally?


y now refers to the same object as x. alt text

How do we know that? It can be verified by checking the id of the object that these two variables x and y are pointing to.

id(y) == id(x)
# output

We can also print the id of the object

print(f"id of the object pointed by x:{id(x)}")
print(f"id of the object pointed by y:{id(y)}") 

# output
#your id value might be different from mine but the two ids printed must be the same
id of the object pointed by x:140733799282752 
id of the object pointed by y:140733799282752

Now, what if we assign a different value to y?


This will create another integer object with the value 40 and y will now refer to 40 instead of 10. alt text How to check Again, we will use id() to see the ids of the objects.

print(x) # outputs 10
print(y) # outputs 40
print(f"id of the object pointed by x:{id(x)}")
print(f"id of the object pointed by y:{id(y)}")  

# output
id of the object pointed by x:140733799282752
id of the object pointed by y:140733799283712

As we can see from above, the two ids are now different which means a new object with value 40 is created and y refers to that object now.

If we wish to assign some other value to variable x

x = "python"

# output

We will get an object id that is different from the id “140733799282752” printed by id(x) for integer object 10 previously.

So what happened to the integer object 10? The integer object 10 now remains unreferenced and can no longer be accessed. Python has a smart garbage collection system that looks out for objects that are no longer accessible and reclaims the memory so that it can be used for some other purpose. alt text One last question: What if we create two integer objects with the same value?

p = 100
q = 100

Before I answer this question. Let's check their ids:

print(f"id of the object pointed by x:{id(p)}")
print(f"id of the object pointed by y:{id(q)}") 
# output
id of object pointed by x:140733799285632
id of object pointed by y:140733799285632

So what python does is optimize memory allocation by creating a single integer object with value 100 and then points both the variables p and q towards it.

Let's check one more example-

m = 350
n = 350

print(f"id of object pointed by x:{id(m)}")
print(f"id of object pointed by y:{id(n)}") 

# output
id of the object pointed by x:1783572881872
id of the object pointed by y:1783572881936

To our surprise the ids of the integer object 300 referred to by m and n are different. What is going on here?? Python allocates memory for integers in the range [-5, 256] at startup, i.e., integer objects for these values are created and ids are assigned. This process is also known as integer caching. So whenever an integer is referenced in this range, python variables point to the cached value of that object. That is why the object id for integer object 100 referenced by p and q print the same ids. For integers outside the range [-5, 256], their objects are created as and when they are defined during program implementation. This is the reason why the ids for integer object 350 referenced by m and n are different. As mentioned earlier, variables point to the objects stored in memory. Hence variables are free to point to object of any type.

x = 10 # x points to an object of 'int' type
x = ["python", 20, "apple"] # x now points to an object of type 'list'
x = "python" # x now points to a string type object

I hope you enjoyed reading it. Feel free to suggest improvements to the article or any other topic that you would like to know more about.