0% found this document useful (0 votes)
7 views108 pages

100 Helpful Python Tips You Can Learn Before Finishing Your Morning Coffee - by

The document discusses various Python programming techniques and features, including the 'for-else' loop, list comprehensions, and the use of enums. It provides examples of how to implement these features in code, demonstrating their practical applications. The document also touches on advanced topics such as unpacking lists and using the 'ast' module for converting strings to lists.

Uploaded by

Chainika Kapoor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views108 pages

100 Helpful Python Tips You Can Learn Before Finishing Your Morning Coffee - by

The document discusses various Python programming techniques and features, including the 'for-else' loop, list comprehensions, and the use of enums. It provides examples of how to implement these features in code, demonstrating their practical applications. The document also touches on advanced topics such as unpacking lists and using the 'ast' module for converting strings to lists.

Uploaded by

Chainika Kapoor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 108

!"#$%&'()*%+ ,-.

/0)&*1/2/*34%(+4(

F-"*'/@(*<*G0((*>(>#(0H-+$7*&2-0%(&*$(G2*2'%&*>-+2'C
3%D+*"E*G-0*6()%">*/+)*D(2*/+*(I20/*-+(

5/2-&*6-0%+/ 5-$$-.

6/7*89:*;9;8 < ;=*>%+*0(/) < ?%&2(+

3/@(

!""#$%&'()&#*+,-./#01'2#3.)#45/#6%57/
8%(.7%#91/12-1/:#3.)7#;.7/1/:#4.((%%
ABC*320%+D&*/+)*2"E$(&*/0(*%>>"2/#$(
!'-2-*#7*J(I-*-+*K+&E$/&'

Python is quite popular nowadays, mainly due to its simplicity, and easiness to
learn.

You can use it for a wide range of tasks like data science and machine learning,
web development, scripting, automation, etc.

Since this is a pretty long article and you want to reach its end before you finish
your coffee, why don’t we just start?

Okay, here we go…

!=#>?&2%@#A./B1,1./#1/21B%#5#>(.7@#&..'
Despite all the Python code that you have seen so far, chances are that you may
have missed the following “for-else” which I also got to see for the first time a
couple of weeks ago.

This is a “for-else” method of looping through a list, where despite having an


iteration through a list, you also have an “else” condition, which is quite unusual.

This is not something that I have seen in other programming languages like Java,
Ruby, or JavaScript.

Let’s see an example of how it looks in practice.

Let’s say that we are trying to check whether there are no odd numbers in a list.

Let’s iterate through it:


:
numbers = [2, 4, 6, 8, 1]

for number in numbers:


if number % 2 == 1:
print(number)
break
else:
print("No odd numbers")

In case we find an odd number, then that number will be printed since break will
be executed and the else branch will be skipped.

Otherwise, if break is never executed, the execution flow will continue with the
else branch.

In this example, we are going to print 1.

<=#C%,#%&%D%/,2#(7.D#5#&12,#)21/:#/5D%B#E5715F&%2

my_list = [1, 2, 3, 4, 5]
:
one, two, three, four, five = my_list

G=#C%,#/#&57:%2,#.7#/#2D5&&%2,#%&%D%/,2#1/#5#&12,#)21/:#,-%#D.B)&%
-%5'H

import heapq

scores = [51, 33, 64, 87, 91, 75, 15, 49, 33, 82]

print(heapq.nlargest(3, scores)) # [91, 87, 82]


print(heapq.nsmallest(5, scores)) # [15, 33, 33, 49, 51]

I=#*522#E5&)%2#(7.D#5#&12,#52#D%,-.B#57:)D%/,2
We can extract all elements of a list using “*”:
:
1:mylist=[1,2,3,4]
2

3:print(mylist) #[1,2,3,4]
4

5:print(*mylist) #1234

my_list = [1, 2, 3, 4]

print(my_list) # [1, 2, 3, 4]

print(*my_list) # 1 2 3 4

This can be helpful in situations where we want to pass all elements of a list as
method arguments:
:
1:defsumofelements(*arg):
2 total = 0

foriinarg:
total+=i

returntotal

8
9• result=sumofelements(*[1,2,3,4])

10:print(result) #10
11•

def sum_of_elements(*arg):
total = 0
for i in arg:
total += i

return total

result = sum_of_elements(*[1, 2, 3, 4])


print(result) # 10

J=#C%,#5&&#,-%#%&%D%/,2#1/#,-%#D1BB&%#.(#,-%#&12,
:
_, *elements_in_the_middle, _ = [1, 2, 3, 4, 5, 6, 7, 8]

print(elements_in_the_middle) # [2, 3, 4, 5, 6, 7]

K=#L221:/#D)&,1'&%#E5715F&%2#1/#M)2,#./%#&1/%

•one,two,three,four=1,2,3,4

one, two, three, four = 1, 2, 3, 4


:
N=#612,#A.D'7%-%/21./2
You can loop through the elements in a list in a single line in a very
comprehensive way.

Let’s see that in action in the following example:

numbers=[1,2,3,4,5,6,7,8]

2
3:evennumbers = [numberfornumberinnumbersifnumber%2==01
4

5 :print(evennumbers) #[2,4,6,8]
6

numbers = [1, 2, 3, 4, 5, 6, 7, 8]

even_numbers = [number for number in numbers if number % 2 ==


0]

print(even_numbers) # [2, 4, 6, 8]

We can do the same with dictionaries, sets, and generators.

Let’s see another example, but now for dictionaries.


:
dictionary = {'first_element': 1, 'second_element': 2,
'third_element': 3, 'fourth_element': 4}

odd_value_elements = {key: num for (key, num) in


dictionary.items() if num % 2 == 1}

print(odd_value_elements) # {'first_element': 1,
'third_element': 3}

This example was inspired by this article.

O=#?/)D%75,%#7%&5,%B#1,%D2#.(#,-%#25D%#A./A%',#E15#?/)D
From the docs:

An Enum is a set of symbolic names bound to unique values. They


are similar to global variables, but they offer a more useful
repr(), grouping, type-safety, and a few other features.

Here is an example:
:
from enum import Enum

class Status(Enum):
NO_STATUS = -1
NOT_STARTED = 0
IN_PROGRESS = 1
COMPLETED = 2

print(Status.IN_PROGRESS.name) # IN_PROGRESS
print(Status.COMPLETED.value) # 2

P=#Q%'%5,#2,71/:2#R1,-.),#&..'1/:
:
:string ="Abc"
2

3:print(string*5)#AbcAbcAbcAbcAbe
4

string = "Abc"

print(string * 5) # AbcAbcAbcAbcAbc

!"=#4.D'57%#G#/)DF%72#M)2,#&1S%#1/#;5,-
If you have a value and you want to compare it whether it is between two other
values, there is a simple expression that you use in Math:

1 < x < 10

That is the algebraic expression that we learn in elementary school. However, you
can also use that same expression in Python as well.

Yes, you heard that right. You have probably done comparisons of such form up
until now:

1 < x and x < 10

For that, you simply need to use the following in Python:


:
1 < x < 10

This doesn’t work in Ruby, the programming language that was developed with
the intention of making programmers happy. This turns out to be working in
JavaScript as well.

I was really impressed seeing such a simple expression not being talked about
more widely. At least, I haven’t seen it being mentioned that much.

!!=#;%7:%#B1A,1./571%2#1/#5#21/:&%#7%5B5F&%#&1/%
This is available as of Python 3.9:
:
first_dictionary = {'name': 'Fatos', 'location': 'Munich'}
second_dictionary = {'name': 'Fatos', 'surname': 'Morina',
'location': 'Bavaria, Munich'}
result = first_dictionary | second_dictionary
print(result)
# {'name': 'Fatos', 'location': 'Bavaria, Munich', 'surname':
'Morina'}

!<=#91/B#,-%#1/B%T#.(#5/#%&%D%/,#1/#5#,)'&%

books = ('Atomic habits', 'Ego is the enemy', 'Outliers',


'Mastery')

print(books.index('Mastery')) # 3
:
!G=#4./E%7,#5#2,71/:#1/,.#5#&12,#.(#2,71/:2
Let’s say that you get the input in a function that is a string, but it is supposed to
be a list:

input = "[1,2,3]"

You don’t need it in that format. You need it to be a list:

input = [1,2,3]

Or maybe you the following response from an API call:

input = [[1, 2, 3], [4, 5, 6]]

Rather than bothering with complicated regular expressions, all you have to do is
import the module ast and then call its method literal_eval:
:
import ast

def string_to_list(string):
return ast.literal_eval(string)

That’s all you need to do.

Now you will get the result as a list, or list of lists, namely like the following:
:
import ast

def string_to_list(string):
return ast.literal_eval(string)

string = "[[1, 2, 3],[4, 5, 6]]"


my_list = string_to_list(string)
print(my_list) # [[1, 2, 3], [4, 5, 6]]

!I=#LE.1B#>,71E15&@#D12,5S%2#F+#)21/:#/5D%B#'575D%,%72
Let’s assume that you want to find the difference between 2 numbers. The
difference is not commutative:

a - b != b -a
:
However, we may forget the ordering of the parameters which can cause “trivial”
mistakes:

:defsubtract(a,b):
2 return a -
-b

3
4•

5:print((subtract(1,3))) -2

6 :print((subtract(3,1))) #2

def subtract(a, b):


return a - b

print((subtract(1, 3))) # -2
print((subtract(3, 1))) # 2

To avoid such potential mistakes, we can simply use named parameters and the
ordering of parameters doesn’t matter anymore:
:
def subtract(a, b):
return a - b

print((subtract(a=1, b=3))) # -2
print((subtract(b=3, a=1))) # -2

!J=#*71/,#D)&,1'&%#%&%D%/,2#R1,-#5#21/:&%#'71/,UV#2,5,%D%/,

1:print(1,2,3,"a","z","thisishere","hereissomethingelse")
2•
:
print(1, 2, 3, "a", "z", "this is here", "here is something
else")

!K=#*71/,#D)&,1'&%#%&%D%/,2#1/#,-%#25D%#&1/%

print("Hello", end="")
print("World") # HelloWorld
print("Hello", end=" ")
print("World") # Hello World
print('words', 'with', 'commas', 'in', 'between', sep=', ')
# words, with, commas, in, between

!N=#*71/,#D)&,1'&%#E5&)%2#R1,-#5#A)2,.D#2%'575,.7#1/#F%,R%%/#%5A-
E5&)%
You can do advanced printing quite easily:
:
print("29", "01", "2022", sep="/") # 29/01/2022

print("name", "domain.com", sep="@") # [email protected]

!O=#3.)#A5//.,#)2%#5#/)DF%7#5,#,-%#F%:1//1/:#.(#,-%#/5D%#.(#5
E5715F&%

four_letters = “abcd” # this works

4_letters = “abcd” # this doesn’t work


:
!P=#3.)#A5//.,#)2%#5/#.'%75,.7#5,#,-%#F%:1//1/:#.(#,-%#/5D%#.(#5
E5715F&%

+variable = “abcd” # this doesn’t work

<"=#3.)#A5//.,#-5E%#"#52#,-%#(172,#B1:1,#1/#5#/)DF%7

number = 0110 # this doesn't work


:
<!=#3.)#A5/#)2%#,-%#)/B%72A.7%#A-575A,%7#5/+R-%7%#1/#,-%#/5D%#.(#5
E5715F&%
This means, anywhere you want, as many times as you want in the name of a
variable:

a______b = "abcd" # this works


_a_b_c_d = "abcd" # this also works

I am not encouraging you to use it, but in case you see a weird naming of a
variable like that, know that it is actually a valid name of a variable.

<<=#3.)#A5/#2%'575,%#F1:#/)DF%72#R1,-#,-%#)/B%72A.7%
This way it can be easier to read them.
:
print(1_000_000_000) # 1000000000
print(1_234_567) # 1234567

<G=#Q%E%72%#,-%#.7B%71/:#.(#5#&12,

1 :mylist=['a','b','c','d'1

3:mylist.reverse()
4

5:print(mylist) #I'd','c','b','a'l
6

my_list = ['a', 'b', 'c', 'd']


:
my_list.reverse()

print(my_list) # ['d', 'c', 'b', 'a']

<I=#W&1A%#5#2,71/:#)21/:#5#2,%'#()/A,1./

my_string = "This is just a sentence"


print(my_string[0:5]) # This

# Take three steps forward


print(my_string[0:10:3]) # Tsse

<J=#Q%E%72%#2&1A1/:
:
my_string = "This is just a sentence"
print(my_string[10:0:-1]) # suj si sih

# Take two steps forward


print(my_string[10:0:-2]) # sjs i

<K=#*57,15&#W&1A1/:#R1,-#M)2,#,-%#F%:1//1/:#.7#%/B1/:#1/B%T
Indices indicating the start and end of slicing can be optional.
:
my_string = "This is just a sentence"
print(my_string[4:]) # is just a sentence

print(my_string[:3]) # Thi

<N=#9&..7#B1E121./

print(3/2) # 1.5
print(3//2) # 1

<O=#X1((%7%/A%#F%,R%%/#YY#5/B#>12@
“is” checks whether 2 variables are pointing to the same object in memory.

“==” compares the equality of values that these 2 objects hold.


:
1 firstlist=[1,2, 31
2 secondlist =[1,2,3]
3•

4:#Istheiractualvaluethesame?
5 print(firstlist == secondlist) #True
6

7:#Aretheypointingtothesameobjectinmemory
8:print(firstlistis secondlist)
9:#False,sincetheyhavesamevalues
10:#butindifferentobjectsinmemory
11•
12:

13:thirdlist =firstlist
14 :

15:print(thirdlistis firstlist)
16:#True,sincebothpointtothesameobjectinmemory
17•

first_list = [1, 2, 3]
second_list = [1, 2, 3]

# Is their actual value the same?


print(first_list == second_list) # True

# Are they pointing to the same object in memory


print(first_list is second_list)
# False, since they have same values, but in different objects
in memory

third_list = first_list

print(third_list is first_list)
# True, since both point to the same object in memory
:
<P=#;%7:%#<#B1A,1./571%2#H)1AS&+

1:dictionaryone =("a":1,"b":2}
2 :dictionarytwo =
("c":3,"d":4}
3•

4 merged = {**dictionaryone,**dictionarytwo}
5
6:print(merged) #('a':1,'b':2,'c':3,'d':4}
7•

dictionary_one = {"a": 1, "b": 2}


dictionary_two = {"c": 3, "d": 4}

merged = {**dictionary_one, **dictionary_two}

print(merged) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

G"=#4-%AS#R-%,-%7#5#2,71/:#12#&57:%7#,-5/#5/.,-%7#2,71/:
:
first = "abc"
second = "def"
print(first < second) # True
second = "ab"
print(first < second) # False

G!=#4-%AS#R-%,-%7#5#2,71/:#2,57,2#R1,-#5#'57,1A)&57#A-575A,%7#R1,-.),
)21/:#,-%#1/B%T#"
:
my_string = "abcdef"
print(my_string.startswith("b")) # False

G<=#91/B#,-%#)/1H)%#1B#.(#5#E5715F&%#)21/:#1BUV

print(id(1)) # 4325776624
print(id(2)) # 4325776656
print(id("string")) # 4327978288
:
GG=#Z/,%:%72[#(&.5,2[#2,71/:2[#F..&%5/2[#5/B#,)'&%2#57%#1DD),5F&%
When we assign a variable to an immutable type such as integers, floats, strings,
booleans, and tuples, then this variable points to an object in memory.

In case we assign to that variable another value, the original object is still in
memory, but the variable pointing to it is lost:

number = 1
print(id(number)) # 4325215472
print(id(1)) # 4325215472

number = 3
print(id(number)) # 4325215536
print(id(1)) # 4325215472
:
GI=#W,71/:2#5/B#,)'&%2#57%#1DD),5F&%
This was already mentioned in the previous point but wanted to emphasize it
since this is quite important.

name = "Fatos"
print(id(name)) # 4422282544

name = "fatos"
print(id(name)) # 4422346608
:
my_tuple = (1, 2, 3, 4)
print(id(my_tuple)) # 4499290128

my_tuple = ('a', 'b')


print(id(my_tuple)) # 4498867584

GJ=#612,2[#2%,2[#5/B#B1A,1./571%2#57%#D),5F&%
This means that we can change the object without losing binding to it:
:
cities = ["Munich", "Zurich", "London"]
print(id(cities)) # 4482699712

cities.append("Berlin")
print(id(cities)) # 4482699712

Here is another example with sets:


:
1:myset =(1,2,3,4}
2:print(id(myset)) #4352726176
3:

4:myset.add(5)
5:print(id(myset)) #4352726176
6

my_set = {1, 2, 3, 4}
print(id(my_set)) # 4352726176

my_set.add(5)
print(id(my_set)) # 4352726176

GK=#3.)#A5/#,)7/#5#2%,#1/,.#5/#1DD),5F&%#2%,
This way, you can no longer modify it:
:
my_set = frozenset(['a', 'b', 'c', 'd'])

my_set.add("a")

If you do that, an error will be thrown:

AttributeError: 'frozenset' object has no attribute 'add'

GN=#L/#>1(\%&1(@#F&.AS#A5/#%T12,#R1,-.),#,-%#%&2%#F&.AS#5,#,-%#%/B
However, “elif” cannot stand on its own without an “if” step before it:
:
def check_number(number):
if number > 0:
return "Positive"
elif number == 0:
return "Zero"

return "Negative"

print(check_number(1)) # Positive

GO=#4-%AS#R-%,-%7#<#2,71/:2#57%#5/5:75D2#)21/:#2.7,%BUV
:
def check_if_anagram(first_word, second_word):
first_word = first_word.lower()
second_word = second_word.lower()
return sorted(first_word) == sorted(second_word)

print(check_if_anagram("testinG", "Testing")) # True


print(check_if_anagram("Here", "Rehe")) # True
print(check_if_anagram("Know", "Now")) # False

GP=#C%,#,-%#E5&)%#.(#5#A-575A,%7#1/#]/1A.B%
:
print(ord("A")) # 65
print(ord("B")) # 66
print(ord("C")) # 66
print(ord("a")) # 97

I"=#C%,#S%+2#.(#5#B1A,1./57+#1/#5#21/:&%#&1/%
:
dictionary = {"a": 1, "b": 2, "c": 3}

keys = dictionary.keys()

print(list(keys)) # ['a', 'b', 'c']

I!=#C%,#E5&)%2#.(#5#B1A,1./57+#1/#5#21/:&%#&1/%
:
dictionary = {"a": 1, "b": 2, "c": 3}

values = dictionary.values()

print(list(values)) # [1, 2, 3]

I<=#WR5'#S%+2#5/B#E5&)%2#.(#5#B1A,1./57+
:
dictionary = {"a": 1, "b": 2, "c": 3}

reversed_dictionary = {j: i for i, j in dictionary.items()}

print(reversed) # {1: 'a', 2: 'b', 3: 'c'}

IG=#3.)#A5/#A./E%7,#5#F..&%5/#E5&)%#1/,.#5#/)DF%7

print(int(False)) # 0
print(float(True)) # 1.0

II=#3.)#A5/#)2%#F..&%5/#E5&)%2#1/#571,-D%,1A#.'%75,1./2
“False” is 0, whereas “True” is 1.
:
x = 10
y = 12
result = (x - False)/(y * True)
print(result) # 0.8333333333333334

IJ=#3.)#A5/#A./E%7,#5/+#B5,5#,+'%#1/,.#5#F..&%5/#E5&)%
:
print(bool(.0)) # False
print(bool(3)) # True
print(bool("-")) # True
print(bool("string")) # True
print(bool(" ")) # True

IK=#4./E%7,#5#E5&)%#1/,.#5#A.D'&%T#/)DF%7
:
print(complex(10, 2)) # (10+2j)

You can also convert a number into a hexadecimal number:

print(hex(11)) # 0xb

IN=#LBB#5#E5&)%#1/#,-%#(172,#'.21,1./#1/#5#&12,
If you use append(), you are going to insert new values from the right.
:
We can also use insert() to specify the index and the element where we want to
insert this new element. In our case, we want to insert it in the first position, so
we use 0 as the index:

my_list = [3, 4, 5]

my_list.append(6)
my_list.insert(0, 2)
print(my_list) # [2, 3, 4, 5, 6]

IO=#65DFB5#()/A,1./2#A5/#./&+#F%#1/#./%#&1/%
You cannot have lambdas in more than one line.

Let’s try the following:


:
comparison = lambda x: if x > 3:
print("x > 3")
else:
print("x is not greater than 3")

The following error is going to be thrown:

result = lambda x: if x > 3:


^
SyntaxError: invalid syntax

IP=#4./B1,1./5&2#2,5,%D%/,2#1/#&5DFB5#2-.)&B#5&R5+2#1/A&)B%#,-%
>%&2%@#'57,
Let’s try the following:
:
comparison = lambda x: "x > 3" if x > 3

We are going to get the following error:

comparison = lambda x: "x > 3" if x > 3


^
SyntaxError: invalid syntax

Noe that this is a feature of the conditional expression and not of the lambda
itself.

J"=#(1&,%7UV#7%,)7/2#5#/%R#.FM%A,
:
my_list = [1, 2, 3, 4]

odd = filter(lambda x: x % 2 == 1, my_list)

print(list(odd)) # [1, 3]
print(my_list) # [1, 2, 3, 4]

J!=#D5'UV#7%,)7/2#5#/%R#.FM%A,
:
my_list = [1, 2, 3, 4]

squared = map(lambda x: x ** 2, my_list)

print(list(squared)) # [1, 4, 9, 16]


print(my_list) # [1, 2, 3, 4]

J<=#75/:%UV#1/A&)B%2#5#2,%'#'575D%,%7#,-5,#D5+#/.,#F%#S/.R/#,-5,
D)A-
:
for number in range(1, 10, 3):
print(number, end=" ")
# 1 4 7

JG=#75/:%UV#2,57,2#F+#B%(5)&,#5,#"
So you don’t need to include it at all.
:
def range_with_zero(number):
for i in range(0, number):
print(i, end=' ')

def range_with_no_zero(number):
for i in range(number):
print(i, end=' ')

range_with_zero(3) # 0 1 2
range_with_no_zero(3) # 0 1 2
:
JI=#3.)#B./^,#/%%B#,.#A.D'57%#,-%#&%/:,-#R1,-#"
If the length is greater than 0, then it is by default True, so you don’t really need
to compare it with 0:

def get_element_with_comparison(my_list):
if len(my_list) > 0:
return my_list[0]

def get_first_element(my_list):
:
if len(my_list):
return my_list[0]

elements = [1, 2, 3, 4]
first_result = get_element_with_comparison(elements)
second_result = get_element_with_comparison(elements)

print(first_result == second_result) # True

JJ=#3.)#A5/#B%(1/%#,-%#25D%#D%,-.B#D)&,1'&%#,1D%2#1/21B%#,-%#25D%
2A.'%
However, only the last one is called, since it overrides previous ones.
:
def get_address():
return "First address"

def get_address():
return "Second address"

def get_address():
return "Third address"

print(get_address()) # Third address


:
JK=#3.)#A5/#5AA%22#'71E5,%#'7.'%7,1%2#%E%/#.),21B%#,-%17#1/,%/B%B
2A.'%

class Engineer:
def __init__(self, name):
self.name = name
self.__starting_salary = 62000

dain = Engineer('Dain')
print(dain._Engineer__starting_salary) # 62000

JN=#4-%AS#,-%#D%D.7+#)25:%#.(#5/#.FM%A,
:
import sys

print(sys.getsizeof("bitcoin")) # 56

JO=#3.)#A5/#B%(1/%#5#D%,-.B#,-5,#A5/#F%#A5&&%B#R1,-#52#D5/+
'575D%,%72#52#+.)#R5/,
:
def get_sum(*arguments):
result = 0
for i in arguments:
result += i
return result

print(get_sum(1, 2, 3)) # 6
print(get_sum(1, 2, 3, 4, 5)) # 15
print(get_sum(1, 2, 3, 4, 5, 6, 7)) # 28

JP=#3.)#A5/#A5&&#,-%#'57%/,#A&522^2#1/1,15&1_%7#)21/:#2)'%7UV#.7#'57%/,
A&522^2#/5D%
Calling the parent’s class initializer using super():
:
class Parent:
def __init__(self, city, address):
self.city = city
self.address = address

class Child(Parent):
def __init__(self, city, address, university):
super().__init__(city, address)
self.university = university

child = Child('Zürich', 'Rämistrasse 101', 'ETH Zürich')


print(child.university) # ETH Zürich

Calling the parent’s class using the parent class’s name:


:
class Parent:
def __init__(self, city, address):
self.city = city
self.address = address

class Child(Parent):
def __init__(self, city, address, university):
Parent.__init__(self, city, address)
self.university = university

child = Child('Zürich', 'Rämistrasse 101', 'ETH Zürich')


print(child.university) # ETH Zürich

Note that calls to parent initializers using __init__() and super() can only be
used inside the child class’s initializer.
:
K"=#3.)#A5/#7%B%(1/%#,-%#>`@#.'%75,.7#1/21B%#+.)7#.R/#A&522%2
Whenever you use the + operator between two int data types, then you are going
to find their sum.

However, when you use it between two string data types, you are going to merge
them:

print(10 + 1) # Adding two integers using '+'


print('first' + 'second') # Merging two strings '+'

This represents the operator overloading.

You can also use it with your own classes as well:


:
class Expenses:
def __init__(self, rent, groceries):
self.rent = rent
self.groceries = groceries

def __add__(self, other):


return Expenses(self.rent + other.rent,
self.groceries + other.groceries)

april_expenses = Expenses(1000, 200)


may_expenses = Expenses(1000, 300)

total_expenses = april_expenses + may_expenses


print(total_expenses.rent) # 2000
print(total_expenses.groceries) # 500
:
K!=#3.)#A5/#5&2.#7%B%(1/%#,-%#>a@#5/B#>YY@#.'%75,.72#1/21B%#+.)7#.R/
A&522%2
Here is another example of an operation overloadding that you can define
yourself:

class Game:
def __init__(self, score):
self.score = score

def __lt__(self, other):


return self.score < other.score
:
first = Game(1)
second = Game(2)

print(first < second) # True

Similarly, like the two previous cases, we can override the __eq__() function
based on our own needs:

class Journey:
def __init__(self, location, destination, duration):
self.location = location
self.destination = destination
self.duration = duration

def __eq__(self, other):


:
return ((self.location == other.location) and
(self.destination == other.destination) and
(self.duration == other.duration))

first = Journey('Location A', 'Destination A', '30min')


second = Journey('Location B', 'Destination B', '30min')

print(first == second)

You can also analogously define:

__sub__() for -

__mul__() for *

__truediv__() for /

__ne__() for !=

__ge__() for >=

__gt__() for >

K<=#3.)#A5/#B%(1/%#5#A)2,.D#'71/,5F&%#E%721./#(.7#5/#.FM%A,#.(#5#A&522
:
class Rectangle:
def __init__(self, a, b):
self.a = a
self.b = b

def __repr__(self):
return repr('Rectangle with area=' + str(self.a *
self.b))

print(Rectangle(3, 4)) # 'Rectangle with area=12'

KG=#WR5'#A52%2#.(#A-575A,%72#1/#5#2,71/:
:
string = "This is just a sentence."
result = string.swapcase()

print(result) # tHIS IS JUST A SENTENCE.

KI=#4-%AS#1(#5&&#A-575A,%72#57%#R-1,%#2'5A%2#1/#5#2,71/:
:
string = " "
result = string.isspace()

print(result) # True

KJ=#4-%AS#1(#5&&#A-575A,%72#1/#5#2,71/:#57%#%1,-%7#5&'-5F%,2#.7
/)DF%72

name = "Password"
print(name.isalnum()) # True, because all characters are
alphabets

name = "Secure Password "


print(name.isalnum()) # False, because it contains whitespaces

name = "S3cur3P4ssw0rd"
print(name.isalnum()) # True

name = "133"
print(name.isalnum()) # True, because all characters are
numbers
:
KK=#4-%AS#1(#5&&#A-575A,%72#1/#5#2,71/:#57%#5&'-5F%,2

string = "Name"
print(string.isalpha()) # True

string = "Firstname Lastname"


print(string.isalpha()) # False, because it contains
whitespace

string = “P4ssw0rd”
print(string.isalpha()) # False, because it contains numbers

KN=#Q%D.E%#A-575A,%72#(7.D#,-%#71:-,#F52%B#./#,-%#57:)D%/,
:
string = "This is a sentence with "

# Remove trailing spaces from the right


print(string.rstrip()) # "This is a sentence with"

string = "this here is a sentence…..,,,,aaaaasd"

print(string.rstrip(“.,dsa”)) # "this here is a sentence"

You can similarly remove characters from the left based on the argument:

string = "ffffffffFirst"

print(string.lstrip(“f”)) # First
:
KO=#4-%AS#1(#5#2,71/:#7%'7%2%/,2#5#/)DF%7

string = "seven"
print(string.isdigit()) # False

string = "1337"
print(string.isdigit()) # True

string = "5a"
print(string.isdigit()) # False, because it contains the
character 'a'

string = "2**5"
print(string.isdigit()) # False

KP=#4-%AS#1(#5#2,71/:#7%'7%2%/,2#5#4-1/%2%#/)DF%7
:
# 42673 in Arabic numerals
string = "四⼆六七三"

print(string.isdigit()) # False
print(string.isnumeric()) # True

N"=#4-%AS#1(#5#2,71/:#-52#5&&#1,2#R.7B2#2,57,1/:#R1,-#5/#)''%7A52%
A-575A,%7
:
string = "This is a sentence"
print(string.istitle()) # False

string = "10 Python Tips"


print(string.istitle()) # True

string = "How to Print A String in Python"


# False, because of the first characters being lowercase in
"to" and "in"
print(string.istitle())

string = "PYTHON"
print(string.istitle()) # False. It's titlelized version is
"Python"

N!=#b%#A5/#)2%#/%:5,1E%#1/B%T%2#1/#,)'&%2#,..
:
numbers = (1, 2, 3, 4)

print(numbers[-1]) # 4
print(numbers[-4]) # 1

N<=#c%2,#5#&12,#5/B#5#,)'&%#1/21B%#5#,)'&%
:
mixed_tuple = (("a"*10, 3, 4), ['first', 'second', 'third'])

print(mixed_tuple[1]) # ['first', 'second', 'third']


print(mixed_tuple[0]) # ('aaaaaaaaaa', 3, 4)

NG=#d)1AS&+#A.)/,#,-%#/)DF%7#.(#,1D%2#5/#%&%D%/,#5''%572#1/#5#&12,
,-5,#25,12(1%2#5#A./B1,1./

names = ["Besim", "Albert", "Besim", "Fisnik", "Meriton"]

print(names.count("Besim")) # 2

NI=#3.)#A5/#%521&+#:%,#,-%#&52,#/#%&%D%/,2#)21/:#2&1A%UV
:
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
slicing = slice(-4, None)

# Getting the last 3 elements from the list


print(my_list[slicing]) # [4, 5, 6]

# Getting only the third element starting from the right


print(my_list[-3]) # 4

You can also use slice() for other usual slicing tasks, like:
:
string = "Data Science"

# start = 1, stop = None (don't stop anywhere), step = 1


# contains 1, 3 and 5 indices
slice_object = slice(5, None)

print(string[slice_object]) # Science

NJ=#4.)/,#,-%#/)DF%7#.(#,1D%2#5/#%&%D%/,#5''%572#1/#5#,)'&%

my_tuple = ('a', 1, 'f', 'a', 5, 'a')

print(my_tuple.count('a')) # 3

NK=#C%,#,-%#1/B%T#.(#5/#%&%D%/,#1/#5#,)'&%
:
my_tuple = ('a', 1, 'f', 'a', 5, 'a')

print(my_tuple.index('f')) # 2

NN=#C%,#2)F\,)'&%2#F+#D5S1/:#M)D'2

my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

print(my_tuple[::3]) # (1, 4, 7, 10)


:
NO=#C%,#2)F\,)'&%2#2,57,1/:#(7.D#5/#1/B%T

my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

print(my_tuple[3:]) # (4, 5, 6, 7, 8, 9, 10)

NP=#Q%D.E%#5&&#%&%D%/,2#(7.D#5#&12,[#2%,[#.7#B1A,1./57+
:
my_list = [1, 2, 3, 4]
my_list.clear()
print(my_list) # []

my_set = {1, 2, 3}
my_set.clear()
print(my_set) # set()

my_dict = {"a": 1, "b": 2}


my_dict.clear()
:
print(my_dict) # {}

O"=#e.1/#<#2%,2
One way is to use the method union() which returns a new set as a result of the
joining:

first_set = {4, 5, 6}
second_set = {1, 2, 3}

print(first_set.union(second_set)) # {1, 2, 3, 4, 5, 6}

Another one is method update, which inserts the element of the second set into
the first one:
:
first_set = {4, 5, 6}
second_set = {1, 2, 3}

first_set.update(second_set)

print(first_set) # {1, 2, 3, 4, 5, 6}

O!=#4./B1,1./#1/21B%#,-%#'71/,#()/A,1./
:
def is_positive(number):
print("Positive" if number > 0 else "Negative") # Positive

is_positive(-3)

O<=#;)&,1'&%#A./B1,1./2#5,#5#21/:&%#1(\2,5,%D%/,
:
math_points = 51
biology_points = 78
physics_points = 56
history_points = 72

my_conditions = [math_points > 50, biology_points > 50,


physics_points > 50, history_points > 50]

if all(my_conditions):
print("Congratulations! You have passed all of the exams.")
else:
print("I am sorry, but it seems that you have to repeat at
least one exam.")
# Congratulations! You have passed all of the exams.

OG=#L,#&%52,#./%#A./B1,1./#12#D%,#.),#.(#D5/+#1/#5#21/:&%#1(\2,5,%D%/,

math_points = 51
biology_points = 78
physics_points = 56
:
history_points = 72

my_conditions = [math_points > 50, biology_points > 50,


physics_points > 50, history_points > 50]

if any(my_conditions):
print("Congratulations! You have passed all of the exams.")
else:
print("I am sorry, but it seems that you have to repeat at
least one exam.")
# Congratulations! You have passed all of the exams.

OI=#L/+#/./\%D',+#2,71/:#12#%E5&)5,%B#,.#07)%

print(bool("Non empty")) # True

print(bool("")) # False
:
OJ=#L/+#/./\%D',+#&12,[#,)'&%[#.7#B1A,1./57+#12#%E5&)5,%B#,.#07)%

LE(+*%+*/EE M(2*&2/02()

print(bool([])) # False
print(bool(set([]))) # False

print(bool({})) # False
print(bool({"a": 1})) # True

OK=#f,-%7#E5&)%2#,-5,#%E5&)5,%#,.#95&2%#57%#c./%[#>95&2%@#5/B#,-%
/)DF%7#"
:
8CAN 89

print(bool(False)) # False
print(bool(None)) # False
print(bool(0)) # False

ON=#3.)#A5//.,#A-5/:%#,-%#E5&)%#.(#5#:&.F5&#E5715F&%#M)2,#F+
D%/,1./1/:#1,#1/21B%#5#()/A,1./
:
string = "string"

def do_nothing():
string = "inside a method"

do_nothing()

print(string) # string

You need to use the access modifier global as well:


:
string = "string"

def do_nothing():
global string
string = "inside a method"

do_nothing()

print(string) # inside a method


:
OO=#4.)/,#,-%#/)DF%7#.(#%&%D%/,2#1/#5#2,71/:#.7#&12,#)21/:#4.)/,%7
(7.D#>A.&&%A,1./2@

from collections import Counter

result = Counter("Banana")
print(result) # Counter({'a': 3, 'n': 2, 'B': 1})

result = Counter([1, 2, 1, 3, 1, 4, 1, 5, 1, 6])


print(result) # Counter({1: 5, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1})

OP=#4-%AS#1(#<#2,71/:2#57%#5/5:75D2#)21/:#4.)/,%7
:
from collections import Counter

def check_if_anagram(first_string, second_string):


first_string = first_string.lower()
second_string = second_string.lower()
return Counter(first_string) == Counter(second_string)

print(check_if_anagram('testinG', 'Testing')) # True


print(check_if_anagram('Here', 'Rehe')) # True
print(check_if_anagram('Know', 'Now')) # False

You can also check whether 2 strings are anagrams using sorted():
:
def check_if_anagram(first_word, second_word):
first_word = first_word.lower()
second_word = second_word.lower()
return sorted(first_word) == sorted(second_word)

print(check_if_anagram("testinG", "Testing")) # True


print(check_if_anagram("Here", "Rehe")) # True
print(check_if_anagram("Know", "Now")) # False

P"=#4.)/,#,-%#/)DF%7#.(#%&%D%/,2#)21/:#>A.)/,@#(7.D#>1,%7,..&2@
:
from itertools import count

my_vowels = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']

current_counter = count()

string = "This is just a sentence."

for i in string:
if i in my_vowels:
print(f"Current vowel: {i}")
print(f"Number of vowels found so far:
{next(current_counter)}")

This is the result in the console:

Current vowel: i
Number of vowels found so far: 0
Current vowel: i
Number of vowels found so far: 1
Current vowel: u
Number of vowels found so far: 2
Current vowel: a
Number of vowels found so far: 3
:
Current vowel: e
Number of vowels found so far: 4
Current vowel: e
Number of vowels found so far: 5
Current vowel: e
Number of vowels found so far: 6

P!=#W.7,#%&%D%/,2#.(#5#2,71/:#.7#&12,#F52%B#./#,-%17#(7%H)%/A+
Counter from the collections module by default doesn’t order elements based on
their frequencies.

from collections import Counter

result = Counter([1, 2, 3, 2, 2, 2, 2])


print(result) # Counter({2: 5, 1: 1, 3: 1})
print(result.most_common()) # [(2, 5), (1, 1), (3, 1)]
:
P<=#91/B#,-%#D.2,#(7%H)%/,#%&%D%/,#1/#5#&12,#1/#M)2,#./%#&1/%

my_list = ['1', 1, 0, 'a', 'b', 2, 'a', 'c', 'a']

print(max(set(my_list), key=my_list.count)) # a

PG=#X1((%7%/A%#F%,R%%/#A.'+UV#5/B#B%%'A.'+UV
Here is the explanation from the docs:

A shallow copy constructs a new compound object and then (to


the extent possible) inserts references into it to the objects
found in the original.

A deep copy constructs a new compound object and then,


recursively, inserts copies into it of the objects found in the
original.

Maybe, an even more comprehensive description can be found here:


:
A shallow copy means constructing a new collection object and
then populating it with references to the child objects found
in the original. In essence, a shallow copy is only one level
deep. The copying process does not recurse and therefore won’t
create copies of the child objects themselves.

A deep copy makes the copying process recursive. It means first


constructing a new collection object and then recursively
populating it with copies of the child objects found in the
original. Copying an object this way walks the whole object
tree to create a fully independent clone of the original object
and all of its children.

Here is an example for the copy():

first_list = [[1, 2, 3], ['a', 'b', 'c']]

second_list = first_list.copy()

first_list[0][2] = 831

print(first_list) # [[1, 2, 831], ['a', 'b', 'c']]


print(second_list) # [[1, 2, 831], ['a', 'b', 'c']]
:
Here is an example for the deepcopy() case:

import copy

first_list = [[1, 2, 3], ['a', 'b', 'c']]

second_list = copy.deepcopy(first_list)

first_list[0][2] = 831

print(first_list) # [[1, 2, 831], ['a', 'b', 'c']]


print(second_list) # [[1, 2, 3], ['a', 'b', 'c']]

PI=#3.)#A5/#5E.1B#,-7.R1/:#%77.72#R-%/#,7+1/:#,.#5AA%22#5#/./\
%T12,%/,#S%+#1/#5#B1A,1./57+
:
If you use a usual dictionary and try to access a non-existent key, then you are
going to get an error:

my_dictonary = {"name": "Name", "surname": "Surname"}

print(my_dictonary["age"])

Here it’s the error thrown:

KeyError: 'age'

We can avoid such errors using defaultdict():


:
from collections import defaultdict

my_dictonary = defaultdict(str)
my_dictonary['name'] = "Name"
my_dictonary['surname'] = "Surname"

print(my_dictonary["age"])

PJ=#3.)#A5/#F)1&B#+.)7#.R/#1,%75,.7
:
class OddNumbers:
def __iter__(self):
self.a = 1
return self
:
def __next__(self):
x = self.a
self.a += 2
return x

odd_numbers_object = OddNumbers()
iterator = iter(odd_numbers_object)

print(next(iterator)) # 1
print(next(iterator)) # 3
print(next(iterator)) # 5

PK=#3.)#A5/#7%D.E%#B)'&1A5,%2#(7.D#5#&12,#1/#5#21/:&%#&1/%

my_set = set([1, 2, 1, 2, 3, 4, 5])


print(list(my_set)) # [1, 2, 3, 4, 5]
:
PN=#*71/,#,-%#'&5A%#R-%7%#5#D.B)&%#12#&.A5,%B

import torch

print(torch) # <module 'torch' from '/Users/...'

PO=#3.)#A5/#A-%AS#R-%,-%7#5#E5&)%#12#/.,#'57,#.(#5#&12,#)21/:#>/.,#1/@
:
odd_numbers = [1, 3, 5, 7, 9]
even_numbers = []

for i in range(9):
if i not in odd_numbers:
even_numbers.append(i)

print(even_numbers) # [0, 2, 4, 6, 8]

PP=#X1((%7%/A%#F%,R%%/#2.7,UV#5/B#2.7,%BUV
sort() sorts the original list.

sorted() returns a new sorted list.


:
groceries = ['milk', 'bread', 'tea']

new_groceries = sorted(groceries)
# new_groceries = ['bread', 'milk', 'tea']

print(new_groceries)

# groceries = ['milk', 'bread', 'tea']


print(groceries)

groceries.sort()

# groceries = ['bread', 'milk', 'tea']


print(groceries)
:
!""=#C%/%75,%#)/1H)%#ZX2#)21/:#,-%#))1B#D.B)&%
UUID stands for Universally Unique Identifier.

import uuid

# Generate a UUID from a host ID, sequence number, and the


current time
print(uuid.uuid1()) # 308490b6-afe4-11eb-95f7-0c4de9a0c5af

# Generate a random UUID


print(uuid.uuid4()) # 93bc700b-253e-4081-a358-24b60591076a

8./)2g#!"!=#W,71/:#12#5#'71D1,1E%#B5,5#,+'%#1/#*+,-./
If you come from a Java background, you know that String in Java is a non-
primitive data type, because it refers to an object.

In Python, a string is a primitive data type.


:
I hope you learned at least something from this article.

Happy coding!

!"#$%&'%()*%+,-%./*"/01-
O7*,-./0)&*1/2/*34%(+4(

P@(07*,'"0&)/7:*2'(*Q/0%/#$(*)($%@(0&*2'(*@(07*#(&2*-G*,-./0)&*1/2/*34%(+4(R*G0->*'/+)&H-+
2"2-0%/$&*/+)*4"22%+DH()D(*0(&(/04'*2-*-0%D%+/$*G(/2"0(&*7-"*)-+S2*./+2*2-*>%&&C*,/T(*/*$--TC

M(2*2'%&*+(.&$(22(0
:
U#-"2 V($E ,(0>& !0%@/47

2-3%3,-%4-5"&6%/''
:

You might also like