dgplug member blogs


Read the latest posts from dgplug member blogs.

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 Pradhvan

For the last couple of weeks I have been actively job hunting and in one of the place I interviewed I was asked if I can do take-home assignment in Go. Since I had already mentioned in the interview I had been learning Go on the side. I agreeded finishing the assignment in Go thinking this might be a good challenge to take on and by doing this I might have a chance to showcase my ability of picking up new things quickly.

Plus having a deadline to complete the take-home assignment in a week could also accelerate my Go learning, as it provides a time based goal to work towards.

Gopher Coffee Gif

So for a week I spend most of my time reading parts of Learning Go, refering to tutorials Learn Go with Tests, watching old episodes from justforfunc: Programming in Go, a lot of stackoverflowing and talking to friends who use Go as primary language at work to get some pointers(no pun intended) on best practices, blogs to follow etc.

After a week, I finished writing gogrep, a command line program written in Go that implements Unix grep like functionality.

gogrep has a fairly small subset of features it can search a pattern from a file or a directory and also has support for flags like

  • -i : Make the seach case sensitive.
  • -c : Count number of matches.
  • -o : Store the search results in a file.
  • -B : Print 'n' lines before the match.

While adding these features I also added a fair bit of tests to the project to see how tests are written in Go.

At the moment the test coverage of the entire project is around 72.0% where all the major packages that server as helper or have buisness logic have a coverage greater than 83% and a very few have 100%.

Since gogrep is my first Go project, I do have some loose opinions about the language and the tools it offer. Primarly from the prespective of Pythonista, who has been using Python as a primarly language for the last four years.

  • Go does not have classes and it's probably good: If you are coming from a background of classes and methods, you can relate some of it with receiver functions. Receiver functions come very close to behaving like methods for a class. Having written a few receiver functions to for a struct the straight forward use case becomes a no brainer but it might get a bit complicated once you start refactoring a code the second or the third time.

  • Poniter! Oh my! : If you have every done pointer airthmetic in C/C++ you know the pain. Thank god in Go you don't have to deal with pointer airthmetic. You still have to be careful since you are dealing with memory addresses and it can get complicated but it's defenitely not that bad. You get use to it.

  • Tooling: I coded the entire project in VSCode and I loved the Go support it has, go-static check suggestion for code snippetes are quite helpful and for tests automatically changing a color of the test file to red at that instant when the associated function is changed, the whole Developer Experience is amazing. I have heard even better things for GoLand by Jetbrains from folks who write Go daily, can't wait to try that out. Besides that gofmt, golint, go vet and go test were some other things that I found to be really handy. I did not play around much with the debugger so can't comment much on that.

  • Makefile to the resuce: Since go gives you a single binary in the end you have build it every time to check you code changes. Having some automated way like a Makefile makes things really easy. So I would suggest during your initial project setup do invest in making a good automated process for building and checking your changes.

  • Error handeling pattern: Go has this pattern for handling errors which is very straight forward but sometimes it might seem a bit too much in terms of repetitve code.

if err != nil {
// Do something here to log/return error

This seems to be the only way to handle error at least that I know of. So most of my code was be sprinkled with a lot of these statements if err != nil in the top layer of the abstraction, for gogrep it was the main.go when I was calling func ParseFlags() for processing arguments.


// main.go

conf, output, err := parseflag.ParseFlags(os.Args[0], os.Args[1:])

if err == flag.ErrHelp {
    // Print the usage of the CLI
} else if err != nil {
    fmt.Println("Error: \n", err)

func ParseFlags(searchWord string, args []string) (config *Config, output string, err error) {
 // Supressed code 	
err = flags.Parse(args)
if err != nil {
    return nil, buf.String(), err

 // Supressed code
if len(flags.Args()) == 0 {
    return nil, "", fmt.Errorf("missing argument searchword and filename")

 // Supressed code
return &conf, buf.String(), nil
  • Types magic: Since Go is statically typed that means when defenining the variable I have an option to either just declare it with a type and have a zero value in it or directly initializing it with some value.

Even with functions I had to write a signature of input types and output.

func ParseFlags(searchWord string, args []string) (config *Config, output string, err error)

Having types in the function signature and output became such a great advantage later on both developer experience when refactoring and re-reding code that I wrote days back.

I became a fan of types in the codebase to such an extent that now I am all in for type annotations in my Python code if they can give me similar advantages.

  • Things I skipped: One week is a very small time to peak into a language features. So obviously I skipped a lot of Go features too like interfaces(I might have used them like io reader but for sure haven't written them), generics and defenitely did not touch goroutines and channels. One thing that most of the people praise Go for. There might be more but from a birds eye view I can not think anything else.

Overall, it was really fun week of learning something new and not using something that is already in my toolkit.

If I do more Go project in the future I would defenitely like to do a talk “Go for Python Developers” where I talk about my experinces of building a series of projects in both Go and Python like:

  • CLI tool

  • A key value store

  • A fully featured backend system for ecommerce website/twitter clone/blogging engine that will include REST APIs, relational DB, Redis for caching, RabbitMQ as a queue, async workers for processing, etc. As close I can get to the real thing.

Thus giving out more stronger opinions that I can back and giving a much deeper overview on what to expect when working with both the languages.

Gopher Gif

References: – Gopher Gifs: Images


from Pradhvan

2022 in the hindsight was a rough year for me. The start of the year I was super confident on what I wanted this year to be but by the end of it was as clueless as anyone.

Here are some of highlights of the year in particular order that summarise 2022 for me:

  • Gave two talks this year one at PyCascades 2022 and PyLadies Berlin.

  • Mentored a person to give her first ever talk at EuroPython 2022.

  • Attended an in person conference this year after ages. God how I missed those.

  • Did a two week workcation in Himachal Pradesh, turns out I not that into this workcation thing.

  • Got back into coffee brewing. Aeropress for the win!

  • Picked up Japanese as a language this year failed at it miserably. I hope I am more consistent with it next year.

  • Bonded with a lot of childhood friend whom I thought I had grown out of.

  • Started seeing someone.

  • Sent my parents on a 10 day vacation, which I think is the highlight of the year since I always wanted to do something like this for my parents the day I got my first paycheck.

  • Paid the initial down payment for a car for my parents.

  • Quit the job that I always tried too hard to fit in and was affecting my mental health. Took a big risk here quitting without a new job in hand, hope it plays off in the longer run.

I hope 2023 is a bit kinder to me and brings in a stability.


from mrinalraj


We proudly remember the importance of Gandhiji's role in Bihar's Champaran. Not only farmers received partial relief from the Tyrant British law but also made Gandhiji in realizing the grand dream of taking people in India's quest for Freedom using Non-Violence as a tool.

It was during the British Colonial period of 1917. Farmers were craving individual rights to choose what to produce on the rented lands from landlords. Britishers colluded with these greedy Landlords and Nawabs forcing Famers to indigo production as a condition to get the necessary financial loan while purchasing them at a throwaway price. Bihar farmer's life became a mere joke. Everybody felt the pain. All that needed was a little push.


Seeing the Bihar farmers' deteriorating condition, a moneylender, Raj Kumar Shukla persuaded Gandhiji to come and understand the plight of farmers.


On seeing Gandhiji's survey of farmers' plight, British Raj was very cautious about Developments.

British Raj tried all possible tricks to trap him under chains of court. But it acted as a catalyst and the news fell out in nearby villages.

Gandhiji started the Champaran Satyagraha. Soon this started getting attention. British Raj felt the pressure to stop public awareness from spreading like wildfire and get it sorted out soon.


Finally, the deal with farmers was successful. Not only farmers got the raise but also Champaran Satyagrah proved to be the booming ground for Non-Violence. It was for the first time Gandhiji felt the importance of Non-Violence that if exercised by society can become a possible part of India's Independence.


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 mrinalraj

Most probably, you have faced/ heard about the recent Facebook outage. Do you know Cisco Thousand Eyes pinpointed the issue – “Facebook Internal DNS unreachability”

How are Cisco Thousand Eyes able to do it? To explain broadly, it all happens with Agents known as Vintage Points.

  1. External Vantage Points: In these agents, are distributed globally like a public agent.
  2. Internal Vantage Points: Agents are monitoring the enterprise contribute to internal Vantage Points.
  3. End-User Experience: These agents understand the employees and customer experience.

So all these agents cover almost all possible sectors hence are responsible for accurately identifying the issue.

Why Cisco ThousandEyes? To explain the need for Cisco ThousandEyes there is a need to understand the current problem. In the past company relied only on its enterprise Syslog and SNMP protocols to identify and troubleshoot the issues. In this way, the reporting of issues became reactive rather than proactively informing the customer. i.e. customer first used to report the outage then the service provider identifies and troubleshoots it. But this gap is now solved using Cisco ThousandEyes by proactively identifying and troubleshooting before the issue is notifiable to the customer.

Isn't it exciting? Yes, it is.

Here are a few articles related to Cisco ThousandEyes I find useful 1. Link to Issue Reported 2. Link to Complete Analysis of the issue

Next Coming: How Cisco ThousandEyes helping in revolutionizing maintaining high uptime.


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.


from mrinalraj

According to wiki “ Cloud computing is the on-demand availability of computer system resources, especially data storage (cloud storage) and computing power, without direct active management by the user”

Benefits it has brought

With the benefits of Iaas(Infrastructure as a Service) , Paas(Product as a Service) we can now use the service on the go without any headache of maintenance of the facility.

The Difference



from mrinalraj

Today I am very much excited to share with you my first song video on the Dgplug platform via YouTube 'Zara Zara'.

Do you know what gives more satisfaction in life? Is it academics or getting an engineering degree? ;D Mostly it is Nurturing your skills and finding a platform to present yourself.

For me publishing my song gives me more satisfaction. In the end, when the time will come to retire it will not be the CGPAs but the risky path in chasing your passion and the crazy things we did with friends that will keep us smiling :)


from mrinalraj

Yesterday on 1st October was the Foundation Day of The Scriptink. I always imagined how easy it seems to maintain the project made apart from the idea of any normal college projects. The audience always sees only the result and not the path. Coming to the point, Me being in Scriptink I came to know how hard is it to keep maintaining the consistency. U may be wondering, consistency in what way.

Definitely, You would be following our Scriptink through the app, youtube LinkedIn page. More than 2 years of consistency in posting the monthly short videos is a great achievement in itself. This is what the audience sees. But inside a team is working day and night to make this 2 min short video possible.

Not much to say, but Scriptink is all about us and not about I.

Click on this to experience the 2 years journey with us