Comprehensive Python - Basics
Try to go beyond basics of Python. Flashcards will be gradually created and updated ;)
273 flashcards · Programming Languages · by claudehsu
(1) in Python means int number 1 instead of a tuple with number 1 as its sole element. To create a tuple with number 1 only, we do (1,)
Given a list of l = ['MEMCODE', 'SPACED REPITATION', 'FLASHCARD'], how to sort the list according to the length of the string elements using lambda experssion?
l.sort(key=lambda e: len(e)) # or sorted(l, key=lambda e: len(e)) Note: the difference is that the sorted function returns a new sorted list, while the first line sort function does in place sort.
Implement below class constructor. Especially you are creating instance variable class Circle: def __init__(self, radius): self.radius = radius
This is something quite different from programming languages like Java, C#, etc. You need a way to reference to the object itself in the method signature of consturctor.
A list with large amounts of elements consumes much memory. In that case, we can use a generator, which feeds the number on the fly, so no huge memory consumption. def get_x_nums(large_number): i = 0 while i < large_number: yield i i += 1 for i in get_x_nums(10000): print(i)
You may try running the code snippet. Press CTRL+C to interrupt the execution if waiting the program to print out 10000 numbers takes too long time to you :p
Given a list like l = [1, 2, 3, 4, 5]. How to get a list in reverse order with slicing? l[ -1::-1]
Ideally, you can leave the first textbox blank, but for better practicing slicing format, fill in something ;) We can also do l.reverse(), which changes l directly.
How to import the numpy module as name np? import numpy as np
The answer is in the question itself :D
math module contains the value of π, let's import it without importing the entire module. from math import pi
Note: by doing that, you may introduce potential name collision.
In Python, can we put elements of different types in a list? e.g. l = [1, 2, 3, "abc", [1,2,3]] a.) Yes, we can b.) No, we cannot Answer: a
Given a list of l = [1, 2, 3], how to use slice notation to modify the list to [-1, 0, 1, 2, 3]? l[:0] = [-1, 0]
Keep in mind that the 'stop' index/location of slicing is excluded
Given a list of l = [4, 5, 6], after executing l.insert(-1, 'a'), what is l? Answer: [4, 5, 'a', 6]
Don't get confused with -1 on step and -1 on index. -1 on step: means moving backward with one element each time -1 on index: means length-1, so it always points to the last element
Given a list of l = ['a', 'b', 'c', 'd', 'e'], how to delete the elements 'b', 'c' and 'd' with slicing? Answer: del l[1:4]
Given a list of l = ['a', 'b', 'b', 'c', 'd'] if we'd like to remove the duplicate 'b', besides using del, how can we achieve that? Answer: l.remove('b')
To call a method with l removing the first occurance of the element. If no matched value found, ValueError will occur.
Ginve a list l = [3, 7, 2, 1], we can simply get the max/min value with max and min function like max(l). However, if the list contains elements of different types like l = [3, 7, 'two', 'one'], what will happen when calling max(l)?
We will get TypeError Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> max(l) TypeError: '>' not supported between instances of 'str' and 'int'
Distinguish shallow clone and deep clone. original = [[0], 1] shallow = original[:] # above is the shallow clone Now do deep clone. import copy deep_clone = copy.deepcopy(original)
Try shallow[0].extend([1,2]) and then check the original. >>> shallow[0].extend([1,2]) >>>original [[0, 1, 2], 1]
In Python we can swap two values like var1, var2 = var1, var2 Why or what under the hood supports above operation?
Under the hood packing and unpacking suport the operation. The steps are Values on the right side are packed into a tuple Then tuple is unpacked into variables on the left side
With Python's packing/unpacking feature, given a list l = [1, 2, 3, 4, 5] a, b, *c = l, what c is? Answer: [3,4,5] (no space after comma) a, *b, c = l, what b is? Answer: [2,3,4] (no space after comma)
Given a list l = [1, 2, 3], how to convert it to a tuple? Answer: tuple(l)
Items in a set must match below two conditions immutable (all in lowercase) hashable (all in lowercase)
The 2nd bullet is usually ignored and not fully understood by newbies
Given t = (1, 2, 3), set(t) can be executed successfully. Given t = (1, 2, [3]), set(t) indicates TypeError: unhashable type: 'list' How to get over the TypeError?
No way. Elements in a set should be both immutable and hashable. The list [3] makes the tuple t not hashable. Don't get confused with frozenset. A set itself is mutable. If we'd like to put a set into another set, we need to convert the mutable set to frozenset so it becomes immutable and hashable. s = {1, 2, 3} ss = {'a', 'b', frozenset(s)}
Caring about the membership and uniqueness instead of sequence, we use Set in Python. Given a set s = {'a', 'b', 3} how to add another item 'c' into the set? Answer: s.add('c') how to check if the set s contains string 'd'? Answer: 'd' in s
In math, given two sets, we can ask for the intersection, union, etc. for those two. How to do that in Python? Given s1 = {1, 2, 3, 4, 5} s2 = {1, 3, 5, 7, 9} intersection: s1 & s2 gets {1, 3, 5} complement of intersection(not exist in both sets, but exist in either set): s1 ^ s2 gets {2, 4, 7, 9}
Fill in operators like ^ & |. It seems that memcode doesn't support the piple to be the answer for now. Put it there as a reminder. union: s1 | s2 gets {1, 2, 3, 4, 5, 7, 9}
Strings can be considered as sequences of characters, so we can use slice notation on Strings. Given a string s = 'Python', how to extract the string 'tho' with slice notation? Answer: s[2:5]
Are strings list of characters?
No, they are not, because strings cannot be modified. >>> s1 = 'abc' >>> s1 = 'def' The 2nd line does not mean to change the content of the string instance. It simply means to make s1 point to another string instance. On the other hand, a list of characters is mutable. For example, we can simply append other characters to the list.
Recall the situations that we use backward slash for escape sequence.
single character like '\t' and '\"' octal & hexadecimal like '\012' and '\x0A' unicode character like '\u00E1', '\u2713' and '\u4F60\u597D'
print('Hello Python') automatically append the new line character at the end of the output. How to prevent that? Answer: print('Hello Python', end='')
Use single quote instead of double quote in the answer
Given a list as l = ['Hello', 'Python', 'Learners'] how to concatenate the elements and print 'Hello Python Learners' ? Answer: " ".join(l)
Given the string spanning multiple lines as s = "Hello\t\n\nPython\n\tLearns" what's the result if we do s.split()
We will get the list as ['Hello', 'Python', 'Learns'] , because the split method splits the string by white spaces.
Given a string as s = 'first_name|last_name|age|male|female' how to split the string into a list as ['first_name', 'last_name', 'age', 'male|female']
s.split('|', 3)
int function and float function can convert a string to the corresponding int value or float value if the string has the int or float meaning. float('abc') will simply cause ValueError. Now think about what will happen to below two cases int(123.45) int('123.45')
The first line is working. The second line causes ValueError. To fix that, we can do int(float('123.45'))
Given a String as s = "<<<<<Comprehensive Python>>>>>" how to remove the less than and greater than operators around the string content? Answer: s.lstrip("<").rstrip(">") alternatively we can use one method s.strip("<>")
Given a string s = 'Hello Python', if we'd like to find the location/index of a particular letter, for example 'o', we can do either of the below >>> s.find('o') 4 >>> s.index('o') 4 What's the difference between find method and index method?
The difference is in the case that the searching character is not in the string >>> s.find('z') -1 >>> s.index('z') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: substring not found find return -1 index causes ValueError
Given a string s = 'Hello Python', how to know how many 'o' is contained in the string? Answer: s.count('o')
Given a string s = 'Memcode is great!'. How to judge whether the string ends with an exclamation mark? Answer: s.endswith('!') How to judge whether the string starts with an letter 'm'? Answer: s.startswith('m')
Note, for the 2nd case, the return value is false due to case sensitive.
>>> s = 'Hello Python' >>> s.replace('ello', 'i') 'Hi Python' >>> s 'Hello Python' Why after the replace operation, s is still 'Hello Python'?
Because strings are immutable, s.replace returns a new string instead of doing an in-place replacement.
Fill in below blanks with methods for lowercase/upercase switch 'HellO World'.lower() # get 'hello world' 'HellO World'.upper() # get 'HELLO WORLD' 'heLLO World'.capitalize() # get 'Hello world' 'heLLO World'.title() # get 'Hello World' 'heLLO World'.swapcase() # get 'HEllo wORLD'
Fill in below blanks with methods for filling with characters >>> 'Hello Python'.center(20, '=') # get '====Hello Python====' >>> 'Hello Python'.rjust(20, '<') '# get '<<<<<<<<Hello Python' >>> 'Hello Python'.ljust(20, '>') # get 'Hello Python>>>>>>>>'
Given a string s = 'Hello', can we do s.reverse() to get a reversed string?
No, string does not have the reverse() method. list has the reverse() method, and that method does the in-place reverse operation, so immutable types like tuple and string don't have reverse() method. To do the reverse operation on the immutable types, we can either turn the instances of those types into list, do the reverse and then convert to the corresponding types back, or we use reversed() function as below >>> ''.join(reversed('Hello')) 'olleH' >>> reversed((1,2,3)) <reversed object at 0x…
Fill in below blanks with methods to detect the content type >>> '123'.isdigit() # whether the content contains only numbers True >>> '123abc'.isalpha() # whether the content contains only alphabetical False >>> '123abc'.isalnum() # whether the content contains only numbers and alphabetical True >>> 'abc'.islower() # whether the content is the lowercase form True
One module contains some useful constants for us to utilize. import string # import that module string.whitespace # show all the whitespaces string.digits # show all the numbers string.hexdigits # show all the characters representing hexadecimal values string.ascii_lowercase # show all the lower case asc table characters
What's the difference between repr method and str method?
repr is for mainly debug purpose, since it returns the formal string representation. Think it as the serialized string。 str is intended to produce the printable/human-readable string representation, so it is the informal string representation. str applied to any built-in Python objects always calls repr. You can treat the default implementation of str as to call repr.
Fill in below blanks with utilizing the 'format' method '{0} is a high-level, general-purpose programming language.'.format('Python') # get 'Python is a high-level, general-purpose programming language.' '{city} is the capital of {country}'.format(city='Beijing', country='China') # get 'Beijing is the capital of China'
Starting in Python 3.6, f-string is introduced. lang = 'Python' f"{lang} is dynamically typed and garbage-collected." # get 'Python is dynamically typed and garbage-collected'
Given pi = 3.1415926. In f-string, how do we round it to 2 decimal places? f'pi is: {round(pi,2)}' # get 'pi is: 3.14'
What's the difference between string and bytes?
A string is an immutable sequence of Unicode characters A bytes object is a sequence of integers with values from 0 to 255, mainly used to deal with binary data
Some confusing items are listed below string is presented as unicode internally unicode is a set of characters utf-8 is encoding standard, which can be used to present the unicode. With different encoding, unicode is presented differently(as different values). This is the default one to use in Python.
>>> unicode_a_with_acute = '\N{LATIN SMALL LETTER A WITH ACUTE}' >>> unicode_a_with_acute 'á' >>>unicode_a_with_acute.encode(encoding='utf-16') b'\xff\xfe\xe1\x00' >>> unicode_a_with_acute.encode(encoding='utf-8') b'\xc3\xa1' >>> >>> b'\xc3\xa1'.decode() 'á' >>> b'\xff\xfe\xe1\x00'.decode(encoding='utf-16') 'á'
How to create an empty dictionaory? Answer: {}
Given below code snippet x = [] y = {} What will happen if we do? x[0] = 'Hello' y[0] = 'World'
x is defined as an empty list, while y is defined as an empty dictionary. x[0] will cause IndexError, bc in Python we cannot use index notation to assign a value to a position that doesn't exist beforehand. y[0] works well bc y is a dictionary
In one dictionary, can we use keys of different types? For example d = {1: 'a', "two": 2}
Yes, we can and the example code works.
Some common operations with dictionary # check whether a dict contains a particular key my_key in my_dic # return either True or False # iterate and print all the keys with the corresponding values for k, v in my_dict.items(): print(f"key: {k} | val: {v}") # remove the entry with key 'no_need' from the dict del my_dict['no_need'] # retrieve all the keys from the dict my_dict.keys()
What's the difference between my_dict.get('my_key', 'default_value') my_dict.setdefault('my_key', 'default_value')
Both provide the default value when the key is not contained in the dict. The difference is get method needs to be explicitly used every time if you want a safe net, but setdefault method works as if the key/value is added to the dict >>> d = {1: 'a', 'two': 2} # since key 3 is not defined, below will cause error >>> d[3] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 3 # explict use 'get' method to provide value >>> d.get(3, 'three') 'three' # 'setdefault' wor…
Dictionary has a method called 'update', what's the result of executing below code snippet? >>> d1 = {1: 'One', 2: 'er'} >>> d2 = {0: 'Zero', 2: 'Two'} >>> d1.update(d2) >>> d1
{1: 'One', 2: 'Two', 0: 'Zero'} It's like the upsert operation.
Are keys in a dictionary ordered?
When using dictionary, we care more about the key/value relationship, so in the old versions of Python, order of keys is not guaranteed. For ordered keys(or to say ordered dictionary), we can utilize the type defined in collections module. Starting from Python 3.6, dictionaries preserve the order that the keys were created and return them in that order.
We can iterate over the return value of keys(), values() and items() methods of dictionary type. Are those return values lists? If those are not lists, why the design of Python is to return those values, instead of returning lists?
No, those returned values are not list, but they behave like sequences. dict_keys dict_values dict_items Those values dynamically update whenever the dictionary changes.
What kind of objects can be used as keys of dictionary?
object need to meet two conditions immutable hashable: the hash value, which is provided by __hash__() method, never changes throughout the life of the value
Regarding to hashable, how to get the hash value of an object? Is it the same as the id of the object?
To get the hash value we can use hash(obj): the recommend approach and it calls __hash__() under the hood obj.__hash__(): double underscore methods should not be called outside of the class intentionally. >>> t = (1, 2, 3) >>> hash(t) 529344067295497451 >>> t.__hash__() 529344067295497451 >>> id(t) 2709681898304 As above program shows, the id is not equal to the hash value. Remember not all objects are hashable.
Why calling hash() function with some object does not work sometimes? For example >>> d = {1: 'a', 2: 'b'} >>> hash(d) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'dict'
Realize that some objects are not hashable, such as dictionaries, sets, lists and etc. The object passed to hash() function must be hashable. This rule also applies to the case of hashable_obj.__hash__(). When asking for hash value, use hash() function, instead of __hash__() method. One good example is to get the hash value of int >>> hash(1) 1 >>> 1.__hash__() File "<stdin>", line 1 1.__hash__() ^ SyntaxError: invalid decimal literal >>> i = 1 >>> i.__hash__() 1 The issue here is that the peri…
Given a sparse matrix like We can represent the matrix with a 2-dim list as matrix = [[3, 0, -2, 11], [0, 9, 0, 0], [0, 7, 0, 0], [0, 0, 0, -5] Is there a better way to represent the sparse matrix? Especially think about the large sparse matrix case.
Yes, we can utilize dictionary key: a tuple to represent the location, aka row and col of the element value: simply the value of the element with the sample matrix, we have below dictionary matrix = {(0, 0): 3, (0, 2): -2, (0, 3): 11, (1, 1): 9, (2, 1): 7, (3, 3): -5} Once you have a rownum and colnum, you can get the corresponding element as element = matrix.get((rownum. colnum), 0)
Recall the cause that a dictionary is used as cache.
If we have one calculation method taking multiple parameters and consuming much time to do the computation, then we can use the combination of the parameters (maybe as a tuple) as the key, and the calculated result as the value. The use of the cache is something like below def complex_calc(param1, param2, param3): t = (param1, param2, param3) if t not in cache_dict: r = # do the complex calculation cache_dict[t] = r return cache_dict[t] The idea here is the same as the dynamic programming.
In Python, the 'full' loop structure is while condition: loop-body else: post-code Think about what will happen if condition becomes false break is called in the loop-body
Condition becomes false: the post-code section will be executed break gets called in loop body: the post-code section is even also skipped
Fill in the multiple branch 'ladder' case if condition1: body1 elif condition2: body2 else: body3
There is no case or switch statement Python. The ladder structure is the one of the ways we use to handle multiple branches case.
Besides the if ladder structure, is there another approach to handle the multiple branches case?
Yes. We can leverage the dictionary. def foo(): print("Hello World!") def bar(): print("Hi BY!") func_dict = {'normal': foo, 'special':bar} func_to_call = func_dict['special'] func_to_call()
Does Python have for loop? Is that the same as the classical for(init; condition; step) pattern?
Python has the for keyword, but it works as an iterator rather than classical for loop. The for ... in... structure in Python iterates over the values returned by any iterable object - that is any object that can yield a sequence of values.
Say we'd like to go thru from 1 to a very large number. We do for x in range(1, 1000001): print(x) What's the benefit with above implementation compared with iterating over a list containing all those numbers?
range object in Python is iterable, and only one number gets yield in each iteration so only small amount of memory gets consumed. A list full of numbers consumes much more memroy.
Does the constructor of range support step parameter?
Yes, it supports. So we can do for x in range(1, 11, 2): print(x) we get numbers 1, 3, 5, 7, 9 printed out.
Given a list l = [(1, 2), (3, 7), (9, 5)] To calculate the summation of the product of each tuple in the list, we can do summation = 0 for t in l: summation += t[0] * t[1] How to implement above logic with unpacking of tuple?
summation = 0 for e1, e2 in l: summation += e1 * e2 Note: by using above implementation, we indicate to Python that each element of the list is expected to be a tuple containing two elements.
Give below code, what will happen? l = [(1,2,3), (4,5,6), (7,8,9)] for a, b in l: print(f"{a}, {b}")
We will get ValueError ValueError: too many values to unpack (expected 2) We can use the wildcard(variadic technique) like below to handle the issue for a, *b in l: print(f"{a}, {b}") Note b is a list
How to loop over both the indices and items of a list?
Use enumerate built-in function. The function returns a generator which produces a tuple of (index, item) countries = ["China", "United States", "Switzerland"] for idx, item in enumerate(countries): print(f"{idx} - {item}")
zip function is used to combine elements from different iterable objects. For example for e in zip(range(3), ['a', 'b', 'c'], (1, 2, 3)): print(e) What will happen if the length of the iterable objects is different?
zip function works according to the shortest iterable objects. the zip function yields tuples until an input is exhausted.
Besides combining elements from different iterable objects, what else can zip function do?
zip can be used to logically unzip elements into multiple iterable objects, just as the opposite operation of zip. l = [(1, 'a', 'China'), (2, 'b', 'USA'), (3, 'c', 'Switzerland')] t1, *t2 = zip(*l) t1 // get below tuple (1, 2, 3) t2 // get below list of tuple [('a', 'b', 'c'), ('China', 'USA', 'Switzerland')]
What is list comprehension
A special shortcut to create a new list based on iterating thru an existing list and making use of the elements in it. l = ['China', 'USA', 'Switzerland'] [e.upper() for e in l] // we get a new list as below ['CHINA', 'USA', 'SWITZERLAND']
What is dictionary comprehension?
Similar to list comprehension. It is to create new dict based on going thru an existing list and utilizing the elements in it. l = ['China', 'USA', 'Switzerland'] {len(e):e for e in l} // we get {5: 'China', 3: 'USA', 11: 'Switzerland'} Note it's based on existing list, not dictionary d = {1:'China', 2:'USA', 3:'Switzerland', 4:'Japan'} // dictionary itself is iterable and by default, it's iterated by keys of the dict {k*2: d[k] for k in d} // we get {2: 'China', 4: 'USA', 6: 'Switzerland', 8:…
Can we use list/dictionary comprehension with iterable objects other than list?
Yes, other iterable objects are supported. // list comprehension [e.upper() for e in ('a', 'b', 'c')] // we get ['A', 'B', 'C'] // dictionary comprehension { e: e*'*' for e in range(1, 6)} // we get {1: '*', 2: '**', 3: '***', 4: '****', 5: '*****'}
When to use list/dictionary comprehension?
It is recommended to experiment with list/dictionary comprehension any time you find yourself writing a for loop to process a list of items.
What is generator expression?
Generator expressions look a lot like list comprehension, except that () is used instead of []. # g is a generator instead of a tuple g = (e for e in range(1,10) if e % 2 ==0) for ele in g: print(ele) # we get 2 4 6 8
Which symbol is used to separate multiple statements if they are placed on the same line? Answer: ;
What is the recommended practice regarding to tabs vs spaces ?
Always use four spaces as indentation. Python maps a tab to eight spaces, so when tabs are used, we may get unexpected indent error. A practical way is to use IDEs like VS Code, PyCharm and etc. which will convert 'user input tab' to spaces
What's the result of evaluating below string literals? greet = "Hello" \ " World" print(greet)
"Hello World" The backslash escapes the return character, so it looks like "Hello" " World" String literals separated by whitespaces are automatically concatenated.
Does Python support 'falsy' / 'truthy' concept?
Yes. In Python, in a Boolean context 0 and empty values, such as '', None, etc. are False any other values are True
How to test the membership of collection types in Python like list, tuple, set and dictionary?
Use in and not in 'a' in {'a', 'b', 'c'} // we get True 9 in range(9) // we get False
How to test the identity of two objects in Python, meaning whether two references are pointing to the same object?
Use is and is not s1 = "abc" s2 = "abc" s1 is s2 # we get True, bc s1 and s2 point to the same object "abc" True l1 = ["a", "b", "c"] l2 = ["a", "b", "c"] l1 == l2 # True l1 is not l2 # True, bc they point to the different lists which happen to contain the same elements
To do boolean calculation which set of notation is used? 1. and , or and not 2. && , || and !
The 1st set is used. Remember Python is very human readable. >>> b1 = False >>> not b1 True >>> b1 or True True >>> !b1 File "<stdin>", line 1 !b1 ^ SyntaxError: invalid syntax
When operator and and or are used without boolean context, how do they work? For example think about [2] and [] and [3, 4] [] or 0 or 'BY' or False
When and and or are used without boolean context and: return the first falsy item or the last one or: return the first truthy item or the last one
In Python what notations are used to respectively compare equivalence identity
For equivalence, use == and != For identity, use is and is not s1 = 'BY' s2 = 'BY' s1 == s2 # we get True s1 is not s2 # we get False not (s1 is s2) # we get False // you can also try comparing two lists with the same elements l1 = ['Python', 'Scala', 'C#'] l2 = ['Python', 'Scala', 'C#']
Write the if condition of reference x is greater than 5 and less than 10
if 5 < x < 10: # shortcut form is supported print("x matches the condtion") Alternatively we can do if 10 > x > 5: if x > 5 and x < 10:
Is the traditional ternary operator <condition> ? <expr1> : <expr2> supported in Python?
No. The ternary operator does not exist in Python, but Python provide below alternative <expr1> if <cond> else <expr2> p = 'BY' x = 2 if p == 'y'*3 else 3 x // we get 3
Recall the basic form of a function definition in Python. Pay attention to the docstring concept.
def meaningful_func_name(params): "place docstring here" body
In regard to function, is there procedure or subroutine concept in Python?
No, there isn't. In Python, those are actually normal functions. If there is no return statement in the function body, the special Python value None is returned.
Recall the three options of defining function parameters positional parameters: the order of the parameters matter named parameters: aka. keyword arguments variadic parameters: the amount of the parameters is not fixed. Usually the 'extra' arguments are placed in a list or dictionary.
Does positional function parameter support default value?
Yes, it does. Parameters with the default values must be defined as the last ones in the parameter list. def greet(name = "<unknown>"): print(f"Hello {name}") greet("Bella") greet()
Given below function def simple_power(base, power): return 1 if power == 0 \ else base if power == 1 \ else base * simple_power(base, power - 1) print(simple_power(3, 2)) Above positional style is confusing because it doesn't explicitly indicate which one is base and which one is power. How to use named parameter(keyword arguemts) style to improve that?
print(simple_power( power = 2 , base = 3 ) )
For variadic function parameters, there are two forms collect all excess non-keyword arguments into a list l: *l collect all excess keyword-passed arguments into a dictionary d: **d
Is it possible to use both variadic function parameters, list and dictionary, at the same time?
Yes. It's possible in Python. def make_milktea(tea, milk, *favor, **toppings): print(f"Here is your milk tea: {tea} + {milk} | {toppings} @ {favor}") make_milktea("Black Tea", "GM Milk", "Iced", "Less Sugar", bubble="Normal", pudding="Normal")
In Python, are arguments passed by value or by reference?
By reference. That means functions may generate side effect for mutable objects.
What are global variables? How to access them? Write an example.
Global variables are variables that exist outside the function, and can be accessed and changed by other functions that declare them global by code that's not within a function One example def greet(): global name ; name = "Bella" print(f"In the function: {name}") greet() print(f"Outside the function: {name}")
What's the difference between global variables and nonlocal variables?
global: top-level variables nonlocal: variables in the enclosing scope. nonlocal variables are defined in the enclosing function and they cannot be top-level(global) variables in the source file. name = "Bella" assert name == "Bella" def global_change(): global name; name = "Claude" global_change() assert name == "Claude" def nonlocal_change(): name = "Bella" assert name == "Bella" def inner_nonlocal_change(): nonlocal name; name = "Y" assert name == "Y" inner_nonlocal_change() assert name == "…
Given below code snippet name = "Bella" def greet(): target = name assert target == "Bella" greet() What will happen?
The program executes successfully. Like RHS in Javascript, when name is not found in the current scope, Python will move to check below scopes in order until it finds one enclosing scope global scope built-in scope In our case, the `name` defined in the global scope will be identified and used. However this shortcut of using the global variables is not recommended. Explicitly defining the variable as `global` improves the code readability.
In Python, can we assign functions as values to variables?
Yes. Functions are first class citizens in Python and they are treated as any other objects. One practical usage: mimic switch with dictionary from datetime import datetime def day(): print("Good day!") def night(): print("Good night!") func_dict = {"daytime":day, "nighttime":night} hour = datetime.now().strftime("%H") greet_time = 'daytime' if int(hour) <= 17 else 'nighttime' func_dict[greet_time]()
What is lambda expression? Why do we need it? Think about a use case.
Lambda expressions are anonymous little functions that we can quickly define inline. Sometimes defining classical functions is overkill and we just want a quick and simple way to define a function. One example is to pass a function to sorted function l = sorted(['abc', 'a', 'abcd', 'ab'], key=lambda e: len(e) ) print(l)
Define a full_name function to combine first_name and last_name using lambda experssion.
full_name = lambda first_name, last_name: f"{first_name} {last_name}"
Is it possible to define a lambda expression which doesn't have any input parameter?
Yes. greet = lambda : print("Hello. How are you?")