intermediate phython
I assume some people don't understand what's happening here . I had similar problem under c++ ..there is way more complex. Look ! def __add__(self, other): ____return Vector2D(self.x + other.x, self.y + other.y) In __add__ self argument is the first before + and second is that after + __add__ overriding + first = Vector2D(5, 7) second = Vector2D(3, 9) result = first + second It actually looks like that: result = first (second) Second is the argument for first !
#Magic method sample class Vector2D: def __init__(self, x, y): ____self.x = x ____self.y = y def __add__(self, other): ____return Vector2D(self.x + other.x, self.y + other.y) first = Vector2D(5, 7) second = Vector2D(3, 9) result = first + second print(result.x) # 8 print(result.y) # 16 # self.x = 5 # other.x = 3 # self.y = 7 # other.y = 9 #self.x + other.x, self.y + other.y # 5+3 = 8 7+9 = 16
What is the result of this code? class A: ____def method(self): ________print(1) class B(A): ____def method(self): ________print(2) B().method()
2 We can think of it as b = B() b.method()
class O : ____def __init__(self, x) : ________self.x = x class J : ____def __init__(self,y) : ________self.y = y ____def __add__(self, other) : ________return self.y + other.x ____def __radd__(self, other) : ________return self.y + other.x o = O(11) j = J(9) print(o+j)
20
What is the result of this code? def fib(x): ____if x == 0 or x == 1: ________return 1 ____else: ________return fib(x-1) + fib(x-2) print(fib(4))
5 fib(4) = fib(3) + fib(2) = fib(2) + fib(1) + fib(1) + fib(0) = fib(1) + fib(0) + 1 + 1 + 1 = 1 + 1 + 1 + 1 + 1 = 5
What is the result of this code? fib = {1: 1, 2: 1, 3: 2, 4: 3} print(fib.get(4, 0) + fib.get(7, 5))
8
What is the result of this code? fib = {1: 1, 2: 1, 3: 2, 4: 3} print(fib.get(4, 0) + fib.get(7, 5))
8
What is the output of this code? def func(**kwargs): ____print(kwargs["zero"]) func(a = 0, zero = 8)
8 Kwargs is a dictionnary so kwargs[zero] should return the correspondent value of zero def func(**kwargs): return kwargs kwargs2 = {'a' : 0, 'zero' : 8} print(func(a=0, zero=8) == kwargs2) print(kwargs2['zero'])
What is the result of this code? def power(x, y): ____if y == 0: ________return 1 ____else: ________return x * power(x, y-1) print(power(2, 3))
8 power(2,3) 2*power(2,2) 2*2*power(2,1) 2*2*2*power(2,0) 2*2*2*1 return( 2 * return( 2 * return(2 * return 1) ) )
Notice the difference: >>> a, *b = 1, 2, 3, 4 >>> b [2, 3, 4] #list >>> def func(a, *b): print(b) >>> func(1, 2, 3, 4) (2, 3, 4) #tuple
>>>a, *c = 2,4,6,8,10 *c is like a pointer variable which is used to make a tuple from remaining list elements >>>def func(a, *c,) : print (c) func (2,4,6,8,10) Output : This is value of c (4, 6,8,10) # tuple Value of a is 2
class Spam: __egg = 7 def print_egg(self): print(self.__egg) s = Spam() s.print_egg() print(s._Spam__egg) print(s.__egg)
Basically, Python protects those members by internally changing the name to include the class name.
def print_text(): print("Hello world!") print_text = decor(print_text)
In our previous example, we decorated our function by replacing the variable containing the function with a wrapped version.
class Queue: ____def __init__(self, contents): ________self._hiddenlist = list(contents) ____def push(self, value): ________self._hiddenlist.insert(0, value) ____def pop(self): ________return self._hiddenlist.pop(-1) ____def __repr__(self): ________return "Queue({})".format(self._hiddenlist) queue = Queue([1, 2, 3]) print(queue) queue.push(0) print(queue) queue.pop() print(queue) print(queue._hiddenlist)
In the code above, the attribute _hiddenlist is marked as private, but it can still be accessed in the outside code.The __repr__ magic method is used for string representation of the instance.
class Cat: ____def __init__(self, color, legs): ________self.color = color ________self.legs = legs felix = Cat("ginger", 4) print(felix.color)
In the example above, the __init__ method takes two arguments and assigns them to the object's attributes. The __init__ method is called the class constructor.
class SpecialString: ____def __init__(self, cont): ________self.cont = cont ____def __truediv__(self, other): ________line = "=" * len(other.cont) ________return "\n".join([self.cont, line, other.cont]) spam = SpecialString("spam") hello = SpecialString("Hello world!") print(spam / hello)
In the example above, we defined the division operation for our class SpecialString. Note that there is no actual division going on in the example. All the magic method does is add the separating line between the two inputs. In theory, an addition could be performed under the method „__truediv__". That should obviously be avoided as it would cause confusion. As far as I understand it, the benefit is that the operator symbol „/„ is connected to the magic method „__truediv__" and I can therefore call the magic method by just using the „/„ symbol.
nums = { 1: "one", 2: "two", 3: "three" } print(1 in nums) print("three" in nums)
To determine whether a key is in a dictionary, you can use in and not in, just as you can for a list.
words[1] = "cheese"
Trying to reassign a value in a tuple causes an error
numbers = (1, 2, 3) a, b, c = numbers print(a) print(b) print(c)
Tuple unpacking allows you to assign each item in a collection to a variable. This can be also used to swap variables by doing a, b = b, a , since b, a on the right hand side forms the tuple (b, a) which is then unpacked.
words = ("spam", "eggs", "sausages")
Tuples are very similar to lists, except that they are immutable (they cannot be changed).Also, they are created using parentheses, rather than square brackets.
my_tuple = "one", "two", "three" print(my_tuple[0])
Tuples can be created without the parentheses by just separating the values with commas.
What is the result of this code? def make_word(): word = "" for ch in "spam": word +=ch yield word print(list(make_word()))
['s', 'sp', 'spa', 'spam']
Parameters: def __add__(this_object, other_object): Here is what happening in the background after we add the two objects using +. Note that when we overload an operation, the Magic Methods will be automatically called prior to that operation. In this example, we used + and because we have __add__ method, the __add__ method will get called if we use + between two objects.
🔹1🔹 def __add__( first, second ): ____return Vector2D( first.x + second.x , first.y + second.y ) 🔹2🔹 def __add__( first, second ): ____return Vector2D( 5+3 , 7+9) 🔹3🔹 def __add__( first, second ): ____return Vector2D( 8, 16 ) ℹ️ This returns a new object Vector2D(8, 16), and will be assigned to "result" variable, and that "result" will now be a new object that holds the sum of two coordinates of the two Vector2D objects (first and second).
What is the result of this code? tuple = (1, (1, 2, 3)) print(tuple[1])
(1, 2, 3)
def my_func(x, y=7, *args, **kwargs): ____print(kwargs) my_func(2, 3, 4, 5, 6, a=7, b=8) a and b are the names of the arguments that we passed to the function call. The arguments returned by **kwargs are not included in *args.
**kwargs (standing for keyword arguments) allows you to handle named arguments that you have not defined in advance.The keyword arguments return a dictionary in which the keys are the argument names, and the values are the argument values.
What is the output of this code? letters = {"a", "b", "c", "d"} f "e" not in letters: print(1) else: print(2)
1
What is the value of y after this code runs? x, y = [1, 2] x, y = y, x
1
def my_func(x, y=7, *args, **kwargs): ____print(x,"in x of type",type(x)) ____print(y,"in y (override 7) of type",type(y)) ____print(args,"in *args of type",type(args)) ____print(kwargs,"in **kwargs of type",type(kwargs)) my_func(1, 2, 3, 4, 5, 6, a=7, b=8)
1 in x of type <class 'int'> 2 in y (override 7) of type <class 'int'> (3, 4, 5, 6) in *args of type <class 'tuple'> {'a': 7, 'b': 8} in **kwargs of type <class 'dict'> A point to consider is that in defining our function we defined y=7. Here y is a variable and can be modified. Therefore when we call our function y will be assigned the second argument of the function that is given at the time of calling it. That's why my_func(2, 3, 4, 5, 6, a=7, b=8) will return value of y=3. Meaning that in calling the function we gave y the value of 3.
class A : ____def __init__(self, x) : ________self.x = x ____def __add__(self,other) : ________return self.x + other.y class B : ____def __init__(self, y) : ________self.y = y ____def __add__(self,other) : ________return self.y + other.x a = A(9) b = B(1) r = a + b print(r)
10 # a+b = a.__add__(b) = A.__add__(B) = this means we are implimanting B class in A class to use the attributes of B, means we are giving class B as an argument to the __add__() function in class A, there for we wrote other.y means "other = B" so "other.y = B.y" means we are using the attribute in return, by using other.y. This is like recursion, but we are using a whole class except a single function.
What is the output of this code? a, b, c, d, *e, f, g = range(20) print(len(e))
14
What is the output of this code? def test(func, arg): return func(func(arg)) def mult(x): return x * x print(test(mult, 2))
16
What is the result of this code? nums = {1, 2, 3, 4, 5, 6} nums = {0, 1, 2, 3} & nums nums = filter(lambda x: x > 1, nums) print(len(list(nums)))
2 See: nums={1,2,3,4,5,6} nums={0,1,2,3}&nums---> This means: The numbers which are in both sets so 1,2,and 3 are elements which are in both sets So: New sets become nums={1,2,3}and 2 and 3 is elements greater than 1 Ok And: nums=filter(lambda x :x>1,nums)----->that all the numbers in nums greater than 1 that are====>2,3
class Wolf: ____def __init__(self, name, color): ________self.name = name ________self.color = color ____def bark(self): ________print("Grr...") class Dog(Wolf): ____def bark(self): ________print("Woof") husky = Dog("Max", "grey") husky.bark() In the example above, Wolf is the superclass, Dog is the subclass.
A class that inherits from another class is called a subclass.A class that is inherited from is called a superclass.If a class inherits from another with the same attributes or methods, it overrides them. Class wolf ( the superclass) has a method bark() that prints "Grr..." Class Dog (is the subclass of wolf) it also has a method bark() bit that's prints "Woof" Remember if a subclass has the same attributes/method name with the it's superclass... That of the subclass will override that of the superclass.. Hence, why you have "Woof" as output...
Recursion is a very important concept in functional programming.The fundamental part of recursion is self-reference -- functions calling themselves. It is used to solve problems that can be broken up into easier sub-problems of the same type.
A classic example of a function that is implemented recursively is the factorial function, which finds the product of all positive integers below a specified number.For example, 5! (5 factorial) is 5 * 4 * 3 * 2 * 1 (120). To implement this recursively,
Methods of objects we've looked at so far are called by an instance of a class, which is then passed to the self parameter of the method.Class methods are different -- they are called by a class, which is passed to the cls parameter of the method.
A common use of these are factory methods, which instantiate an instance of a class, using different parameters than those usually passed to the class constructor.Class methods are marked with a classmethod decorator.
evens = [i**2 for i in range(10) if i**2 % 2==0] print(evens)
A list comprehension can also contain an if statement to enforce a condition on values in the list. range(10) = [0,1,2,3,4,5,6,7,8,9] x**2 = [0,1,4,9,16,25,36,49,64,81] x**2%2 == 0 means only the even ones from the last list [0,4,16,36,64]
What does this list comprehension create? nums = [i*2 for i in range(10)]
A list of even numbers between 0 and 18
pairs = { 1: "apple", "orange": [2, 3, 4], True: False, 12: "True" } print(pairs.get("orange")) print(pairs.ges(7, 42)) print(pairs.get(12345, "net found"))
A useful dictionary function is get. It does the same thing as indexing, but if the key is not found in the dictionary it returns another specified value instead.
pairs = } 1: "apple", "orange" : [2, 3, 4], True : False, 12 : "True", } print(pairs.get("orange")) print(pairs.get("7, 42)) print(pairs.get(12345, "not found"))
A useful dictionary function is get. It does the same thing as indexing, but if the key is not found in the dictionary it returns another specified value instead.
a, b, *c, d = [1, 2, 3, 4, 5, 6, 7, 8, 9] print(a) print(b) print(c) print(d)
A variable that is prefaced with an asterisk (*) takes all values from the collection that are left over from the other variables c will get assigned the values 3 to 8
Explanation --> husky = Dog('Max', 'grey') # Here husky is the instance of class Dog. class Dog(Wolf): # Here Dog class is inherited from Wolf class. husky.bark() # Here husky instance's bark method is called. So now python will check the class of the husky instance. Which is Dog. Now python will look into the Dog class and search for the bark method. And it finds the method in the class. def bark(self): print('Woof') So python understands it has to print the string 'woof'.
And it prints it out. So--> husky.bark() #output: 'Woof' If bark method was not in the Dog class, then python would search the full class Dog, and then,as bark method is not there, it would check for the inheritence. class Dog(Wolf): So python understands Dog class is inherited from Wolf class and then it starts reading the Wolf class and find the bark method there. That's why if a method is in both the superclass and subclass, only the subclass method is called.
How is *args accessed inside a function? As the tuple *args As the tuple args As the list *args
As the tuple args *args is the pointer variable, which can help you analyze all the variables Tuple name is args not *args
class SpecialString: ____def __init__(self, cont): ________self.cont = cont ____def __gt__(self, other): ________for index in range(len(other.cont)+1): ____________result = other.cont[:index] + ">" + self.cont ____________result += ">" + other.cont[index:] ____________print(result) spam = SpecialString("spam") eggs = SpecialString("eggs") spam > eggs
As you can see, you can define any custom behavior for the overloaded operators. Magic methods for comparisons in word >>> __lt__ for < # less than __le__ for <= # less than or equal to __eq__ for == # equal to __ne__ for != # not equal to __gt__ for > # greater than __ge__ for >= # greater than or equal to
The focal point of Object Oriented Programming (OOP) are objects, which are created using classes.The class describes what the object will be, but is separate from the object itself. In other words, a class can be described as an object's blueprint, description, or definition.You can use the same class as a blueprint for creating multiple different objects.
Classes are created using the keyword class and an indented block, which contains class methods (which are functions).Below is an example of a simple class and its objects.
class Dog: ____def __init__(self, name, color): ________self.name = name ________self.color = color ____def bark(self): ________print("Woof!") fido = Dog("Fido", "brown") print(fido.name) fido.bark() Class attributes are shared by all instances of the class.
Classes can have other methods defined to add functionality to them.Remember, that all methods must have self as their first parameter.These methods are accessed using the same dot syntax as attributes.
def my_func(f, arg): return f(arg) my_func(lambda x : 2*x*x, 5)
Creating a function normally (using def) assigns it to a variable with its name automatically.Python allows us to create functions on-the-fly, provided that they are created using lambda syntax.This approach is most commonly used when passing a simple function as an argument to another function. The syntax is shown in the next example and consists of the lambda keyword followed by a list of arguments, a colon, and the expression to evaluate and return.
def decor(func): def wrap(): print("===========") func() print("===========") return wrap def print_text(): print("Hello world") decorated = decor(print_text) decorated()
Decorators provide a way to modify functions using other functions.This is ideal when you need to extend the functionality of functions that you don't want to modify.
ages = { "Dave": 24, "Mary": 42, "John": 58 } print(ages["Dave"]) print(ages["Mary"])
Dictionaries are another collection type and allow you to map arbitrary keys to values. Dictionaries can be indexed in the same way as lists, using square brackets containing keys. Each element in a dictionary is represented by a key:value pair.
def infinite_sevens(): while True: yield 7 for i in infinite_sevens(): print(i)
Due to the fact that they yield one item at a time, generators don't have the memory restrictions of lists.In fact, they can be infinite! In short, generators allow you to declare a function that behaves like an iterator, i.e. it can be used in a for loop.
def numbers(x): for i in range(x): if i % 2 == 0: yield i print(list(numbers(11)))
Finite generators can be converted into lists by passing them as arguments to the list function. Using generators results in improved performance, which is the result of the lazy (on demand) generation of values, which translates to lower memory usage. Furthermore, we do not need to wait until all the elements have been generated before we start to use them.
def apply_twice(func, arg): return func(func(arg)) def add_five(x): return x + 5 print(apply_twice(add_five, 10))
Functional programming is a style of programming that (as the name suggests) is based around functions.A key part of functional programming is higher-order functions. Higher-order functions take other functions as arguments, or return them as results. The function apply_twice takes another function as its argument, and calls it twice inside its body.
def pure_function(x, y): temp = x + 2*y return temp / (2*x + y)
Functional programming seeks to use pure functions. Pure functions have no side effects, and return a value that depends only on their arguments.This is how functions in math work: for example, the cos(x) will, for the same value of x, always return the same result.Below are examples of pure and impure functions.
def countdown(): i = 5 while i > 0: yield i i -= 1 for i in countdown(): print(i)
Generators are a type of iterable, like lists or tuples.Unlike lists, they don't allow indexing with arbitrary indices, but they can still be iterated through with for loops.They can be created using functions and the yield statement. The yield statement is used to define a generator, replacing the return of a function to provide a result to its caller without destroying local variables.
Which magic method call is made by x[y] = z? x.setitem(z, y) y.__getitem__(x, z) x.__setitem__(y, z)
Here the operation asked is assignment. X[y]= z. The explanation is like in a list (X) We need to insert z at a position y. The syntax is name.__setitem__(position, value) So we will give X.__setitem__(y,z)
class Student : ____def __init__(self, name): ________self.name = name ____def sayHi( self ): ________print("Hi from "+ self .name) s1=Student("Amy") Amy.sayHi()
Hi from Amy
Python also provides magic methods for comparisons. __lt__ for < __le__ for <= __eq__ for == __ne__ for != __gt__ for > __ge__ for >=
If __ne__ is not implemented, it returns the opposite of __eq__.There are no other relationships between the other operators.
We defined a function named decor that has a single parameter func. Inside decor, we defined a nested function named wrap. The wrap function will print a string, then call func(), and print another string. The decor function returns the wrap function as its result.We could say that the variable decorated is a decorated version of print_text -- it's print_text plus something.
In fact, if we wrote a useful decorator we might want to replace print_text with the decorated version altogether so we always got our "plus something" version of print_text.
The __init__ method is the most important method in a class.This is called when an instance (object) of the class is created, using the class name as a function.All methods must have self as their first parameter, although it isn't explicitly passed, Python adds the self argument to the list for you; you do not need to include it when you call the methods. Within a method definition, self refers to the instance calling the method.Instances of a class have attributes, which are pieces of data associated with them.
In this example, Cat instances have attributes color and legs. These can be accessed by putting a dot, and the attribute name after an instance.In an __init__ method, self.attribute can therefore be used to set the initial value of an instance's attributes.
#named function def polynomial(x): return x**2 + 5*x + 4 print(polynomial(-4)) #lambda print(l(ambda x : x**2 + 5*x + 4) (-4))
Lambda functions aren't as powerful as named functions.They can only do things that require a single expression -- usually equivalent to a single line of code.
# a list comprehension cubes = [i**3 for i in range(5)] pirnt(cubes)
List comprehensions are a useful way of quickly creating lists whose contents obey a rule.For example, we can do the following Answer of for example >>> [0, 1, 8, 27, 64]
Strongly private methods and attributes have a double underscore at the beginning of their names. This causes their names to be mangled, which means that they can't be accessed from outside the class.The purpose of this isn't to ensure that they are kept private, but to avoid bugs if there are subclasses that have methods or attributes with the same names.
Name mangled methods can still be accessed externally, but by a different name. The method __privatemethod of class Spam could be accessed externally with _Spam__privatemethod.
This is done by re-assigning the variable that contains our function: print_text = decor(print_text) print_text()
Now print_text corresponds to our decorated version.
Magic methods are special methods which have double underscores at the beginning and end of their names.They are also known as dunders.So far, the only one we have encountered is __init__, but there are several others.They are used to create functionality that can't be represented as a normal method.
One common use of them is operator overloading.This means defining operators for custom classes that allow operators such as + and * to be used on them.An example magic method is __add__ for +.
Their is also dictionary Comprehension: For example to make a dictionary with each item being a pair of a number and its square Square={x:x *x for x in range(6)} print(square)
Output:{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
def function(named_arg, *args): ____print(named_arg) ____print(args) function(1, 2, 3, 4, 5)
Python allows you to have functions with varying numbers of arguments.Using *args as a function parameter enables you to pass an arbitrary number of arguments to that function. The arguments are then accessible as the tuple args in the body of the function. The parameter *args must come after the named parameters to a function.The name args is just a convention; you can choose to use another.
Inheritance provides a way to share functionality between classes.Imagine several classes, Cat, Dog, Rabbit and so on. Although they may differ in some ways (only Dog might have the method bark), they are likely to be similar in others (all having the attributes color and name).
This similarity can be expressed by making them all inherit from a superclass Animal, which contains the shared functionality.To inherit a class from another class, put the superclass name in parentheses after the class name.
def is_even(x): ____if x == 0: ________return True ____else: ________return is_odd(x-1) def is_odd(x): ____return not is_even(x) print(is_odd(17)) print(is_even(23))
Recursion can also be indirect. One function can call a second, which calls the first, which calls the second, and so on. This can occur with any number of functions not(not(not(True)))
num_set = {1, 2, 3, 4, 5} print(3 in num_set)
Sets are similar to lists or dictionaries.They are created using curly braces, and are unordered, which means that they can't be indexed.Due to the way they're stored, it's faster to check whether an item is part of a set using the in operator, rather than part of a list. Sets cannot contain duplicate elements.
first = {1, 2, 3, 4, 5, 6} second = {4, 5, 6, 7, 8, 9} print(first | second) print(first & second) print(first - second) print(second - first) print(first ^ second)
Sets can be combined using mathematical operations.The union operator | combines two sets to form a new one containing items in either.The intersection operator & gets items only in both.The difference operator - gets items in the first set but not in the second.The symmetric difference operator ^ gets items in either set, but not both.
A key part of object-oriented programming is encapsulation, which involves packaging of related variables and functions into a single easy-to-use object -- an instance of a class.A related concept is data hiding, which states that implementation details of a class should be hidden, and a clean standard interface be presented for those who want to use the class.In other programming languages, this is usually done with private methods and attributes, which block external access to certain methods and attributes in a class.
The Python philosophy is slightly different. It is often stated as "we are all consenting adults here", meaning that you shouldn't put arbitrary restrictions on accessing parts of a class. Hence there are no ways of enforcing that a method or attribute be strictly private.
class Vector2D: ____def __init__(self, x, y): ________self.x = x ________self.y = y ____def __add__(self, other): ________return Vector2D(self.x + other.x, self.y + other.y) first = Vector2D(5, 7) second = Vector2D(3, 9) result = first + second print(result.x) print(result.y)
The __add__ method allows for the definition of a custom behavior for the + operator in our class.As you can see, it adds the corresponding attributes of the objects and returns a new object, containing the result.Once it's defined, we can add two objects of the class together.
def add_five(x): return x + 5 nums = [11, 22, 33, 44, 55] result = list(map(add_five, nums)) print(result)
The built-in functions map and filter are very useful higher-order functions that operate on lists (or similar objects called iterables).The function map takes a function and an iterable as arguments, and returns a new iterable with the function applied to each argument.
More magic methods for common operators: __sub__ for - __mul__ for * __truediv__ for / __floordiv__ for // __mod__ for % __pow__ for ** __and__ for & __xor__ for ^ __or__ for |
The expression x + y is translated into x.__add__(y).However, if x hasn't implemented __add__, and x and y are of different types, then y.__radd__(x) is called.There are equivalent r methods for all magic methods just mentioned.
some_list = [ ] def impure(arg): some_list.append(arg)
The function above is not pure, because it changed the state of some_list.
nums = [11, 22, 33, 44, 55] res = list(filter(lambda x: x%2 == 0, nums)) print(res)
The function filter filters an iterable by leaving only the items that match a condition (also called a predicate). Like map, the result has to be explicitly converted to a list if you want to print it.
class A: ____def spam(self): ________print(1) class B(A): ____def spam(self): ________print(2) super().spam() B().spam() super().spam() calls the spam method of the superclass.
The function super is a useful inheritance-related function that refers to the parent class. It can be used to find the method with a certain name in an object's superclass.
There are several magic methods for making classes act like containers. __len__ for len() __getitem__ for indexing __setitem__ for assigning to indexed values __delitem__ for deleting indexed values __iter__ for iteration over objects (e.g., in for loops) __contains__ for in
There are many other magic methods that we won't cover here, such as __call__ for calling objects as functions, and __int__, __str__, and the like, for converting objects to built-in types.
class Cat: ____def __init__(self, color, legs): ________self.color = color ________self.legs = legs felix = Cat("ginger", 4) rover = Cat("dog-colored", 4) stumpy = Cat("brown", 3)
This code defines a class named Cat, which has two attributes: color and legs.Then the class is used to create 3 separate objects of that class.Tap Continue to learn more!
Only immutable objects can be used as keys to dictionaries. Immutable objects are those that can't be changed. So far, the only mutable objects you've come across are lists and dictionaries
This means that you can use strings, integers, booleans, and any other immutable type as dictionary keys.
@decor def print_text(): print("Hello world!")
This pattern can be used at any time, to wrap any function.Python provides support to wrap a function in a decorator by pre-pending the function definition with a decorator name and the @ symbol.If we are defining a function we can "decorate" it with the @ symbol like: This will have the same result as the above code. A single function can have multiple decorators.
nums = [11, 22, 33, 44, 55] result = list(map(lambda x: x + 5, nums)) print(result)
We could have achieved the same result more easily by using lambda syntax. To convert the result into a list, we used list explicitly. The code above is as same as: result = list(x + 5 for x in nums)
import random class VagueList: ____def __init__(self, cont): ________self.cont = cont ____def __getitem__(self, index): ________return self.cont[index + random.randint(-1, 1)] ____def __len__(self): ________return random.randint(0, len(self.cont)*2) vague_list = VagueList(["A", "B", "C", "D", "E"]) print(len(vague_list)) print(len(vague_list)) print(vague_list[2]) print(vague_list[2])
We have overridden the len() function for the class VagueList to return a random number.The indexing function also returns a random item in a range from the list, based on the expression.
When to use a dictionary:- When you need a logical association between a key:value pair.- When you need fast lookup for your data, based on a custom key.- When your data is being constantly modified. Remember, dictionaries are mutable.
When to use the other types:- Use lists if you have a collection of data that does not need random access. Try to choose lists when you need a simple, iterable collection that is modified frequently.- Use a set if you need uniqueness for the elements.- Use tuples when your data cannot/should not change.
class C : ____def __init__(self, u) : ________self.u = u ____def __radd__(self,anaother) : ________return str(self.u) + anaother.z class D : ____def __init__(self, z) : ________self.z = z ____def __radd__(self,anaother) : ________return self.z + str(anaother.u) k = C(77) m = D("Yes") l = k + m print(l)
Yes77
print(words[0])
You can access the values in the tuple with their index, just as you did with lists
nums = {1, 2, 1, 3, 1, 4, 5, 6} print(nums) nums.add(-7) nums.remove(3) print(nums)
You can use the add() function to add new items to the set, and remove() to delete a specific element Duplicate elements will automatically get removed from the set.
Fill in the blanks to create a list of numbers multiplied by 10 in the range of 5 to 9.
a = [x*10 for x in range (5, 9)]
""" Finding prime numbers is a common coding interview task. The given code defines a function isPrime(x), which returns True if x is prime. You need to create a generator function primeGenerator(), that will take two numbers as arguments, and use the isPrime() function to output the prime numbers in the given range (between the two arguments). Sample Input 10 20 Sample Output [11, 13, 17, 19] The given code takes the two arguments as input and passes them to the generator function, outputting the result as a list.
def isPrime(x): if x < 2: return False elif x == 2: return True for n in range(2, x): if x % n ==0: return False return True #your code goes here def primeGenerator(a, b): for x in range(a,b): if isPrime(x): yield x f = int(input()) t = int(input()) print(list(primeGenerator(f, t)))
Given a string as input, use recursion to output each letter of the strings in reverse order, on a new line. Sample Input HELLO Sample Output OLLEH
def spell(txt): #your code goes here return txt[::-1] txt = input() spell(txt) print(spell(txt)) Solution for the last module's project using recursion and list slicing: def spell(txt): #your code goes here # if length of text is 1, that means we are on the last letter ____if len(txt) == 1: _______print(txt) # if length is not 1, do the slicing ____else: ________print(txt[-1]) #print last letter txt = txt[:-1] #redefine text without the last letter spell(txt) #do it all again txt = input() spell(txt)
class Rectangle: ____def __init__(self, width, height): ________self.width = width ________self.height = height ____def calculate_area(self): ________return self.width * self.height ____@classmethod ____def new_square(cls, side_length): ________return cls(side_length, side_length) square = Rectangle.new_square(5) print(square.calculate_area())
new_square is a class method and is called on the class, rather than on an instance of the class. It returns a new object of the class cls. Technically, the parameters self and cls are just conventions; they could be changed to anything else. However, they are universally followed, so it is wise to stick to using them.
def factorial(x): ____if x == 1: ________return 1 ____else: ________return x * factorial(x-1) print(factorial(5))
notice that 5! = 5 * 4!, 4! = 4 * 3!, 3! = 3 * 2!, and so on. Generally, n! = n * (n-1)!.Furthermore, 1! = 1. This is known as the base case, as it can be calculated without performing any more factorials.Below is a recursive implementation of the factorial function. The base case acts as the exit condition of the recursion.Not adding a base case results in infinite function calls, crashing the program.
What is the result of this code? nums = (55, 44, 33, 22) print(max(min(nums[:2]), abs(-42)))
nums[:2] = [55, 44] min(nums) = 44 abs(-42) = 42 max(44, 42) answer is: 44
def apply_twice(func, arg): return func(func(arg)) def add_five(x): return x + 5 print(apply_twice(add_five, 10))
return func(func(arg)) = add_five(add_five(10) = add_five(10+5) = add_five(15) = 15 + 5 = 20 Print (add_twice(add_five,10)) Solution: #first-off, the defined function is called in "def apply_twice (func,arg)" 1.apply_twice(add_five,10): return add_five(add_five(10)) #Now we know what is returned by the first function, we can go to the next function (which happens to be the last one) - "def add_five(x):" 2.add_five(add_five(10)) Let break it down 😉 (a)add_five(x) ->x + 5 return 10 + 5=15 (b)add_five(x) -> x + 5 return 15 + 5= 20 Hope this really helped!!!
Given a string as input, you need to output how many times each letter appears in the string.You decide to store the data in a dictionary, with the letters as the keys, and the corresponding counts as the values.Create a program to take a string as input and output a dictionary, which represents the letter count. Sample Input hello Sample Output {'h': 1, 'e': 1, 'l': 2, 'o': 1}
text = input() dict = {} #your code goes here strdic = {x:text.count(x) for x in text} print(strdic)