loading...

30 Days of Python πŸ‘¨β€πŸ’» - Day 6 - Loops II & Functions

arindamdawn profile image Arindam Dawn Originally published at tabandspace.com ・6 min read

30-days-of-python (30 Part Series)

1) 30 Days of Python πŸ‘¨β€πŸ’» - Day 1 - Introduction 2) 30 Days of Python πŸ‘¨β€πŸ’» - Day 2 - Data Types I 3 ... 28 3) 30 Days of Python πŸ‘¨β€πŸ’» - Day 3 - Data Types II 4) 30 Days of Python πŸ‘¨β€πŸ’» - Day 4 - Data Types III 5) 30 Days of Python πŸ‘¨β€πŸ’» - Day 5 - Conditions & Loops I 6) 30 Days of Python πŸ‘¨β€πŸ’» - Day 6 - Loops II & Functions 7) 30 Days of Python πŸ‘¨β€πŸ’» - Day 7 - Developer Environment 8) 30 Days of Python πŸ‘¨β€πŸ’» - Day 8 - OOP Basics 9) 30 Days of Python πŸ‘¨β€πŸ’» - Day 9 - OOP Pillars 10) 30 Days of Python πŸ‘¨β€πŸ’» - Day 10 - OOP Missing Pieces 11) 30 Days of Python πŸ‘¨β€πŸ’» - Day 11 - Functional Programming Basics 12) 30 Days of Python πŸ‘¨β€πŸ’» - Day 12 - Lambda Expressions & Comprehensions 13) 30 Days of Python πŸ‘¨β€πŸ’» - Day 13 - Decorators 14) 30 Days of Python πŸ‘¨β€πŸ’» - Day 14 - Error Handling 15) 30 Days of Python πŸ‘¨β€πŸ’» - Day 15 - Generators 16) 30 Days of Python πŸ‘¨β€πŸ’» - Day 16 - Module Basics 17) 30 Days of Python πŸ‘¨β€πŸ’» - Day 17 - External Modules 18) 30 Days of Python πŸ‘¨β€πŸ’» - Day 18 - File I/O 19) 30 Days of Python πŸ‘¨β€πŸ’» - Day 19 - Regular Expressions 20) 30 Days of Python πŸ‘¨β€πŸ’» - Day 20 - Debugging and Testing 21) 30 Days of Python πŸ‘¨β€πŸ’» - Day 21 - Scripting Basics 22) 30 Days of Python πŸ‘¨β€πŸ’» - Day 22 - Scripting Extras 23) 30 Days of Python πŸ‘¨β€πŸ’» - Day 23 - Web Scraping 24) 30 Days of Python πŸ‘¨β€πŸ’» - Day 24 - Web Development Basics 25) 30 Days of Python πŸ‘¨β€πŸ’» - Day 25 - Web Development Extras 26) 30 Days of Python πŸ‘¨β€πŸ’» - Day 26 - Machine Learning Basics 27) 30 Days of Python πŸ‘¨β€πŸ’» - Day 27 - ML & Data Science I 28) 30 Days of Python πŸ‘¨β€πŸ’» - Day 28- ML & Data Science II 29) 30 Days of Python πŸ‘¨β€πŸ’» - Day 29 - Automation Testing 30) 30 Days of Python πŸ‘¨β€πŸ’» - Day 30 - Free Python Resources

The joy of coding Python should be in seeing short, concise, readable classes that express a lot of action in a small amount of clear code -- not in reams of trivial code that bores the reader to death.
Guido van Rossum

Starting off from where I left, I continued exploring more loops while playing around with some code. Then I moved on to learning one of the most important things of programming, functions. I came across functions and methods in Python, docstrings, best practices along with scopes in detail. I will try my best to explain in lucid and simple terms.

Loops Continued

While Loops

While loops are another way to run a block of code several times based on a specific condition. We need to be a bit careful when dealing with while loops to accidentally not create an infinite loop that would keep executing till they crash our systems!

hungry = True
while(hungry): # This is always true so it keeps printing until system crashes!
  print('Give me something to eat!!')

But while loops are cool. They are simple to write and easy to read. We just need to tell the interpreter when to stop the loop. It can be either done by using a break statement which stops the loop execution and breaks out of the loop. Another way is to make the condition falsy to stop the execution.

hungry = True
while(hungry):
    print('Give me something to eat!!')
    break # prints only once and stops the loop execution
hungry = True
satisfaction = 0
while(satisfaction < 10):
  satisfaction += 1
  print('Give me something to eat!!') # prints 10 times

Another feature of while loop is that it can be combined with an else block.

hungry = True
satisfaction = 0
while satisfaction < 10:
  satisfaction += 1
  print('Give me something to eat!!')
else:
    print('I am super satisfied now') # gets printed once condition is falsy

It needs to be noted that if the break statement is used in the while block, then the else block is not executed.

While vs For Loop

For loops are usually useful when knowing the range of the iterable that needs to be looped. Whereas while loops can come in handy when we want to perform some task multiple times not knowing the range beforehand.

while True:
  response_from_user = input('Enter some message. Enter bye to exit')
  if(response_from_user == 'bye'):
    break

Apart from the break statement, there are two other statements, continue which instead of breaking out of the loop continues to continue the iteration. pass is not often used but it is sometimes used as a placeholder to continue executing the statements after the loop.
This stack-overflow thread provides a great explanation

Quick Coding Exercise

Let's find the duplicate emails in a list of emails and print them.

email_list = ['roger@hey.com','michael@hey.com','roger@hey.com','prince@gmail.com']
duplicate_emails = []
for email in email_list:
  if email_list.count(email) > 1 and email not in duplicate_emails:
    duplicate_emails.append(email)
print(duplicate_emails)

That was my approach to solve the problem. Let me know how you would have solved it in the comments. Alright! Time to switch to an interesting topic, function.

Functions

Functions are a very important concept and they are present in all programming languages. Functions allow us to define an action(block of code) and then execute the action any number of times without repeating ourselves following the principle of DRY. Up until now, I have been using some of the in-built functions provided by Python such as print, input, len etc. It's time to create one.

def blow_fire(): # This part is called function definition
  print('fire πŸ”₯ πŸ”₯ πŸ”₯')

blow_fire() # This part is called function invocation
blow_fire() # It can be called any number to times to perform some action

Arguments and Parameters

The above function was kind of cool but it has some limitations as well. It can perform only the same action. Let's make it more extensible and make it perform actions at will by passing some data to it

def blower(name, emoji): # parameters
  print(f'{name} {emoji} {emoji} {emoji}')

blower('fire', 'πŸ”₯') # arguments
blower('water', '🌊')

While defining a function, when we provide some data to it to perform some action based on the data, the provided data is called a parameter. A function can be provided with any number of parameters.

When the same function is called or invoked to perform the action, it accepts the data as arguments. It is just terminology but it often confusing and used interchangeably.

The above is also called positional parameters or positional arguments because of the order or position of the parameters or arguments matter.

def blower(name = 'fire', emoji = 'πŸ”₯'): # default parameters
  print(f'{name} {emoji} {emoji} {emoji}')

blower('fire', 'πŸ”₯') # arguments
blower('water', '🌊')
blower() # fire πŸ”₯ # this works as the function has default parameters defined

Return

return is a keyword in Python that is used to return a value from a function. To makes functions more useful, it needs to return some value based on evaluating an expression. If no return statement is specified or the expression of the return statement does not evaluate to a data type, then the function returns None. In JavaScript world, this None can be linked to void.

The return statement terminates the function and exits out of it.

def multiplier(num1, num2):
  return num1 * num2

result = multiplier(2,3)
print(result) # 6

Time to do something cool using the return statement.

def sum(num1):
  def child(num2):
    return num1 + num2
  return child

add_10 = sum(10)
print(add_10(20)) # 30  (Closure!!!)
print(add_10(50)) # 60
print(add_10(100)) # 110

Yay! I just validated that there is the concept of closure in Python as well just like in JavaScript. It is so effective in creating factory functions. In the above block of code, I was able to create a generic function add_10 and pass dynamic arguments to it to generate a different result. How cool is that!

Will explore more about this next week when learning about the functional programming concepts in Python.

Methods are simply functions that are defined inside an object or in other terms, they are 'owned' by the objects. They are called using the object name followed by the . operator to execute or invoke them.

Docstrings

When writing custom functions, it would be very helpful if the objective of the function is mentioned so that other co-workers or users of the code can easily understand what the function does while using them. The IDE would show the info of the function. Also, there are some helper functions and methods to view the information about a function if present.

β€œCode tells you how; Comments tell you why.”
β€” Jeff Atwood (aka Coding Horror)

def test_function():
  '''
  This function just prints test to the console.
  '''
  print('test')

test_function()

β€œCode is more often read than written.”
β€” Guido van Rossum

https://www.programiz.com/python-programming/docstrings

*args and **kwargs

*args is the short form of arguments and **kwargs stands for keyword arguments. These are used when a function needs to accepts any number of arguments or keyword arguments.

def powerful_function(*args):
  print(args)

powerful_function(1,3,2) # (1, 3, 2) --> Returns a tuple

def super_function(**kwargs):
  print(kwargs)

super_function(name='John', age='45') # {'name': 'John', 'age': '45'} --> Returns a dict

https://www.programiz.com/python-programming/args-and-kwargs

In the JavaScript world, the ES6 rest parameters is used to extract all the arguments passed to the function. Another mental model created!

Scope

Scope in simple terms means "Which variables do I have access to ?". This is the kind of question the interpreter asks when reading the code to find the scope of variables. In Python, variables have function scope which means variables defined inside a function cannot be accessed outside of the function.

num = 1
def confusing_function():
    num = 10
    return num

print(num) # 1 => Global Scope
print(confusing_function()) # 10 => Local Scope

These are the scope rules that the Python interpreter follows:

  • Start with local. Is the variable present? Then fetch the value. If not then proceed
  • Is the variable defined in the parent function local scope? Fetch value if present else proceed
  • Is the variable present in the global scope? Fetch value if present else proceed
  • Is the variable a built-in function? Fetch value else exit

Read more about Scope in Python

This is also a great article on scope

That's it for today. I have been able to cover most of the Python basics now. It's time to dig deeper into the advanced topics but before that, I would like to explore and set up the developer environment and all the different kinds of tooling and programs available tomorrow to complete the roadmap for the first week.

I hope I tried to explain my learning process about the language in easy to understand words. Please let me know in the comments if something felt confusing or if you have any other suggestions, thoughts.

Have a great one!

30-days-of-python (30 Part Series)

1) 30 Days of Python πŸ‘¨β€πŸ’» - Day 1 - Introduction 2) 30 Days of Python πŸ‘¨β€πŸ’» - Day 2 - Data Types I 3 ... 28 3) 30 Days of Python πŸ‘¨β€πŸ’» - Day 3 - Data Types II 4) 30 Days of Python πŸ‘¨β€πŸ’» - Day 4 - Data Types III 5) 30 Days of Python πŸ‘¨β€πŸ’» - Day 5 - Conditions & Loops I 6) 30 Days of Python πŸ‘¨β€πŸ’» - Day 6 - Loops II & Functions 7) 30 Days of Python πŸ‘¨β€πŸ’» - Day 7 - Developer Environment 8) 30 Days of Python πŸ‘¨β€πŸ’» - Day 8 - OOP Basics 9) 30 Days of Python πŸ‘¨β€πŸ’» - Day 9 - OOP Pillars 10) 30 Days of Python πŸ‘¨β€πŸ’» - Day 10 - OOP Missing Pieces 11) 30 Days of Python πŸ‘¨β€πŸ’» - Day 11 - Functional Programming Basics 12) 30 Days of Python πŸ‘¨β€πŸ’» - Day 12 - Lambda Expressions & Comprehensions 13) 30 Days of Python πŸ‘¨β€πŸ’» - Day 13 - Decorators 14) 30 Days of Python πŸ‘¨β€πŸ’» - Day 14 - Error Handling 15) 30 Days of Python πŸ‘¨β€πŸ’» - Day 15 - Generators 16) 30 Days of Python πŸ‘¨β€πŸ’» - Day 16 - Module Basics 17) 30 Days of Python πŸ‘¨β€πŸ’» - Day 17 - External Modules 18) 30 Days of Python πŸ‘¨β€πŸ’» - Day 18 - File I/O 19) 30 Days of Python πŸ‘¨β€πŸ’» - Day 19 - Regular Expressions 20) 30 Days of Python πŸ‘¨β€πŸ’» - Day 20 - Debugging and Testing 21) 30 Days of Python πŸ‘¨β€πŸ’» - Day 21 - Scripting Basics 22) 30 Days of Python πŸ‘¨β€πŸ’» - Day 22 - Scripting Extras 23) 30 Days of Python πŸ‘¨β€πŸ’» - Day 23 - Web Scraping 24) 30 Days of Python πŸ‘¨β€πŸ’» - Day 24 - Web Development Basics 25) 30 Days of Python πŸ‘¨β€πŸ’» - Day 25 - Web Development Extras 26) 30 Days of Python πŸ‘¨β€πŸ’» - Day 26 - Machine Learning Basics 27) 30 Days of Python πŸ‘¨β€πŸ’» - Day 27 - ML & Data Science I 28) 30 Days of Python πŸ‘¨β€πŸ’» - Day 28- ML & Data Science II 29) 30 Days of Python πŸ‘¨β€πŸ’» - Day 29 - Automation Testing 30) 30 Days of Python πŸ‘¨β€πŸ’» - Day 30 - Free Python Resources

Posted on by:

arindamdawn profile

Arindam Dawn

@arindamdawn

Software Engineer who loves building user interfaces. In the quest to learn, unlearn and re-learn things.

Discussion

markdown guide
 

Hey, I came up with this odd solution. It's obviously not as clean as yours but I'm trying to apply some concepts you have explained in the previous articles, so there you go :)

email_list = ['roger@hey.com','michael@hey.com','roger@hey.com','prince@gmail.com']
email_set = set(email_list)
duplicate_dict = dict.fromkeys(email_set, 0)

if (email_list.__len__() > 1):
  for email in email_list:
    if (email in email_set):
      duplicate_dict[email]+= 1

  for key in duplicate_dict.keys():
    if (duplicate_dict[key] > 1):
      print(f'"{key}"')

What do you guys think about it?

 

Nice try :) but as Adrian suggested it is not recommended to use dunder methods unless you are planning to override some built-in utility function in a class.

Let me provide an alternate one-line solution using comprehensions which I discovered lately :)

email_list = ['roger@hey.com','michael@hey.com','roger@hey.com','prince@gmail.com']
duplicates = list(set([email for email in email_list if email_list.count(email) > 1 ]))

print(duplicates)

Comprehensions look way cool but they can impact the code readability.

 
 

You should use len(email_list) instead of _ _ len() _ _ (excuse the spaces, the text goes bold if I leave them out). The _ _ method is really an internal method len() looks for on a class. There are lots of them, actually check out the special methods section the docs for info.