diff --git a/135k-keyword-only-arguments.md b/135k-keyword-only-arguments.md new file mode 100644 index 0000000..b862848 --- /dev/null +++ b/135k-keyword-only-arguments.md @@ -0,0 +1,53 @@ +# Keyword Only Arguments +#python #programming #functions #howtodo + +- * and ** [[a1mq-unpacking-sequences-and-iterables]] + +```python +def tag(name, *content, class_=None, **attrs): + """Generate one or more HTML tags""" + if class_ is not None: + attrs['class'] = class_ + attr_pairs = (f' {attr}="{value}"' for attr, value + in sorted(attrs.items())) + attr_str = ''.join(attr_pairs) + if content: + elements = (f'<{name}{attr_str}>{c}' + for c in content) + return '\n'.join(elements) + else: + return f'<{name}{attr_str} />' + +>>> tag('br') +'
' +>>> tag('p', 'hello') +'

hello

' +>>> print(tag('p', 'hello', 'world')) +

hello

+

world

+>>> tag('p', 'hello', id=33) +'

hello

' +>>> print(tag('p', 'hello', 'world', class_='sidebar')) + + +>>> tag(content='testing', name="img") +'' +>>> my_tag = {'name': 'img', 'title': 'Sunset Boulevard', +... 'src': 'sunset.jpg', 'class': 'framed'} +>>> tag(**my_tag) +'' +``` + +- Code above allow you call the function with different number of parameters because of `*content` and `**attrs`. +- Now let force the keyword arguments in the next code +```python +>>> def f(a, *, b): # * force the argument be a keyword, without default value + return a,b +>>> f(1, b=2) +>>> f(1, 2) # Give a error: takes 1 positional argument but 2 were given +``` +- Positional only: +```python +>>> def divmod(a,b,/) # / Force positional only + return (a // b, a % b) +``` diff --git a/1zto-shallow-and-deep-copy.md b/1zto-shallow-and-deep-copy.md new file mode 100644 index 0000000..8597bb3 --- /dev/null +++ b/1zto-shallow-and-deep-copy.md @@ -0,0 +1,47 @@ +# Shallow and Deep Copy +#python #programming #comparison #howtocopy + +- Python uses `shallow` copy as **default** +- `l2 = list(l1)` creates a shallow copy and `l2 = l1[:]` as well. +- It is possible to implement copy functions with `__copy__` and `__deepcopy__` + +```python +>>> l1 = [3, [66, 55, 44], (7, 8, 9)] +>>> l2 = list(l1) +>>> l1.append(100) +>>> l1[1].remove(55) +>>> print('l1:', l1) +>>> print('l2:', l2) +l1: [3, [66, 44], (7, 8, 9), 100] +l2: [3, [66, 44], (7, 8, 9)] +>>> l2[1] += [33, 22] +>>> l2[2] += (10, 11) +>>> print('l1:', l1) +>>> print('l2:', l2) +l1: [3, [66, 44, 33, 22], (7, 8, 9), 100] +l2: [3, [66, 44, 33, 22], (7, 8, 9, 10, 11)] +# They point to the same list yet but with some modifications +# The immutable object tuple does not change inside the mutable one +# List on the l1[1] is the only object which is mutable that change in both object +``` + +- An example with deep copy: + +```python +>>> import copy +>>> bus1 = Bus(['Alice', 'Bill', 'Claire', 'David']) +>>> bus2 = copy.copy(bus1) +>>> bus3 = copy.deepcopy(bus1) +>>> id(bus1), id(bus2), id(bus3) +(4301498296, 4301499416, 4301499752) +>>> bus1.drop('Bill') +>>> bus2.passengers +['Alice', 'Claire', 'David'] +>>> id(bus1.passengers), id(bus2.passengers), id(bus3.passengers) +(4302658568, 4302658568, 4302657800) +>>> bus3.passengers +['Alice', 'Bill', 'Claire', 'David'] +``` + +### References +Ramalho, 2022, 208-213 diff --git a/38lz-zettelkasten.md b/38lz-zettelkasten.md index 13f863f..ab186b3 100644 --- a/38lz-zettelkasten.md +++ b/38lz-zettelkasten.md @@ -5,12 +5,12 @@ Zettelkasten is a tool to create and writing personal thoughts on notes and conn - Organize your information about everything in one place. - Use napkins, papers, voice recording etc. to record your [[ave9-fleeting-notes]]#. It is good idea always have a pen and scratchpad with you. -- - [[ndec-literature-notes]]# need to have at least author and year. But can have page as well. - Zotero is a good tool to be the reference management system. - Use [[8imv-slip-box]]# to store you more important notes that you write with your own words. There you develop not only connection between notes, but ideas and elaborate about it. - We take notes because we want to learn about things [[5quz-why-do-we-take-notes]]# +- In addition we use Zettelkasten to [[h5ky-develop-ideas]]# using group of [[wz0b-permanent-notes]] ### References How to take smart notes (Ahrens, 2017, p29-30) diff --git a/4fmy-packages-for-functional-programming-in-python.md b/4fmy-packages-for-functional-programming-in-python.md new file mode 100644 index 0000000..8c4af74 --- /dev/null +++ b/4fmy-packages-for-functional-programming-in-python.md @@ -0,0 +1,52 @@ +# Packages For Functional Programming in Python +#python #programming #functional #datamodel + +- `operator`: `sum`, `mul` +- `functools`: `reduce` +- `itemgetter`: Catch one item from the sequence [[4dyw-python-sequences]] + - Need to have `__getitem__` implemented +```python +>>> metro_data = [ +... ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)), +... ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)), +... ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)), +... ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)), +... ('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)), +... ] +>>> cc_name = itemgetter(1, 0) +>>> for city in metro_data: +... print(cc_name(city)) +('JP', 'Tokyo') +('IN', 'Delhi NCR') +('MX', 'Mexico City') +('US', 'New York-Newark') +('BR', 'São Paulo') +``` +- `attrgetter`: Catch one attribute from class + +```python +>>> from collections import namedtuple +>>> LatLon = namedtuple('LatLon', 'lat lon') +>>> Metropolis = namedtuple('Metropolis', 'name cc pop coord') +>>> metro_areas = [Metropolis(name, cc, pop, LatLon(lat, lon)) +... for name, cc, pop, (lat, lon) in metro_data] +>>> metro_areas[0] +Metropolis(name='Tokyo', cc='JP', pop=36.933, coord=LatLon(lat=35.689722, +lon=139.691667)) +>>> metro_areas[0].coord.lat +35.689722 +>>> from operator import attrgetter +>>> name_lat = attrgetter('name', 'coord.lat') +>>> +>>> for city in sorted(metro_areas, key=attrgetter('coord.lat')): +... print(name_lat(city)) +... +('São Paulo', -23.547778) +('Mexico City', 19.433333) +('Delhi NCR', 28.613889) +('Tokyo', 35.689722) +('New York-Newark', 40.808611) +``` + +### References +- Ramalho, 2022, p243-247 diff --git a/82os-python-tuples.md b/82os-python-tuples.md index 3a9991d..d6ea6c2 100644 --- a/82os-python-tuples.md +++ b/82os-python-tuples.md @@ -4,6 +4,7 @@ * Tuples: Records if the same information on the same position * Can be used as immutable list if its size does not change * Use less memory +- Inside mutable objects tuple does not change, but a new tuple is created [[1zto-shallow-and-deep-copy]] * They are two subclasses of `tuples` used to store records/hold data. They are * [[01o9-collections-namedtuple]]# * [[07fk-typing-namedtuple]]# diff --git a/8sjh-type-hint.md b/8sjh-type-hint.md index 0712623..20e3dd8 100644 --- a/8sjh-type-hint.md +++ b/8sjh-type-hint.md @@ -6,4 +6,4 @@ - How is: `var_name: some_type` (PEP 484) ### References -Ramalho, 2022, p172-179 +- Ramalho, 2022, p172-179 diff --git a/a8bt-high-order-functions.md b/a8bt-high-order-functions.md new file mode 100644 index 0000000..00e6735 --- /dev/null +++ b/a8bt-high-order-functions.md @@ -0,0 +1,42 @@ +# High Order Functions +#python #functional #programming + +- A function that receive another function or returns a function: Example: `map`, `reduce`, `filter` +- `map` + `filter` = [[ndtq-listcomp]] and [[0651-genexp]] using `if` +- `reduce` = `sum` + +```python +>>> fact = factorial # Function is assign to a variable, functioning like object +>>> fact + +>>> fact(5) +120 +>>> map(factorial, range(11)) + +>>> list(map(factorial, range(11))) # receives factorial +[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800] +>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana'] +>>> sorted(fruits, key=len) # receives the len function +['fig', 'apple', 'cherry', 'banana', 'raspberry', 'strawberry'] +``` + +- [[ey8t-lambda-function]]# +- [[4fmy-packages-for-functional-programming-in-python]]# +- +## Partial + +- Receives one `callable` and `arguments` with predetermined values + +```python +>>> from operator import mul +>>> from functools import partial +>>> triple = partial(mul, 3) +>>> triple(7) +21 +>>> list(map(triple, range(1, 10))) +[3, 6, 9, 12, 15, 18, 21, 24, 27] +``` + +### References +- Ramalho, 2022, p234-236 +- Ramalho, 2022, p247-249 diff --git a/adag-call-by-sharing.md b/adag-call-by-sharing.md new file mode 100644 index 0000000..0079a53 --- /dev/null +++ b/adag-call-by-sharing.md @@ -0,0 +1,28 @@ +# Call by Sharing +#python #programming #carefully + +- Copy the references of the objects, alias for the original +- Change the mutable ones and maintain unchangeable the one that is immutable +- "Principle of the least astonishment" + +```python +class TwilightBus: + """A bus model that makes passengers vanish""" + def __init__(self, passengers=None): + ef __init__(self, passengers=None): + if passengers is None: + self.passengers = [] + else: + self.passengers = list(passengers) + def pick(self, name): + self.passengers.append(name) + def drop(self, name): + self.passengers.remove(name) +``` + +> [!warning] +> **BUG**: Parameters with mutable types as default is a source of bug + + +### References +- Ramalho, 2022, p213-218 diff --git a/aw9b-python-list.md b/aw9b-python-list.md index 2cd6c85..5dcfbf7 100644 --- a/aw9b-python-list.md +++ b/aw9b-python-list.md @@ -3,4 +3,7 @@ - [[ndtq-listcomp]]# - [[j7wj-when-list-is-not-the-best-option-python]]# -- [[nfgb-slicing]] +- If you make a copy of object containing a list, for example, another list, any modifications will be reflected in any + variables referencing this list [[1zto-shallow-and-deep-copy]] +- Slice create a shallow copy of a list [[nfgb-slicing]] +- Does not pass list as default parameter for function [[adag-call-by-sharing]] diff --git a/dcdy-callable-objects.md b/dcdy-callable-objects.md new file mode 100644 index 0000000..a41dab9 --- /dev/null +++ b/dcdy-callable-objects.md @@ -0,0 +1,33 @@ +# Callable Objects +#python #programming #functions #datamodel + +- We have different type of callable objects + - built-in functions: `len` + - classes: `__init__` + - instances: using `__call__` + - generator: with `yield` keyword + - user defined functions with `def` and [[ey8t-lambda-function]] +- They are all called with `()` +- How to know if object is callable: `callable()` + +```python +import random +class BingoCage: + def __init__(self, items): + self._items = list(items) + random.shuffle(self._items) + def pick(self): + try: + return self._items.pop() + except IndexError: + raise LookupError('pick from empty BingoCage') + def __call__(self): + return self.pick() +``` + +- Code above show an example of `__call__` + - Good when you want to obtain the state of the object and preserve it state between calls + - When you implement `decorators` + +### References +- Ramalho, 2022, p237-240 diff --git a/ey8t-lambda-function.md b/ey8t-lambda-function.md new file mode 100644 index 0000000..890e5c1 --- /dev/null +++ b/ey8t-lambda-function.md @@ -0,0 +1,16 @@ +# Lambda Function +#python #programming #functional + +- They are anonymous function, they do not receive name +- If they are too complex transform them into `def`, or, normal function +- Can be used the [[z7l7-walrus]] operator to assign instead of the `=`, however, it is not recommended +- They are used as argument for high order functions + +```python +>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana'] +>>> sorted(fruits, key=lambda word: word[::-1]) +['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry'] +``` + +### References +- Ramalho, 2022, p236-237 diff --git a/iexf-del.md b/iexf-del.md new file mode 100644 index 0000000..d2fdf8b --- /dev/null +++ b/iexf-del.md @@ -0,0 +1,5 @@ +# del +#python #programming #datamodel #garbagecollector + +- `del` delete the reference of the object not the object itself +- `__del__` can be implemented by the user if they think it is important diff --git a/k9ox-difference-between-is-and.md b/k9ox-difference-between-is-and.md new file mode 100644 index 0000000..21371fb --- /dev/null +++ b/k9ox-difference-between-is-and.md @@ -0,0 +1,13 @@ +# Difference between is and == +#python #datamodel #programming #comparison + +- `is` compare the **reference** or the `id` of the object, otherwise `==` compare the **values**. +- `is` is faster than `==` because it does not implement `__eq__` in python +- `is` usually is used to compare to **Singleton** objects like `None` + +```python +x is None +``` + +### References +- Ramalho, 2022, p201-208 diff --git a/tds4-python.md b/tds4-python.md index bc63e6c..9269649 100644 --- a/tds4-python.md +++ b/tds4-python.md @@ -11,3 +11,11 @@ - [[6vep-comprehension]]# - [[f6xw-storage-classes]]# - [[8sjh-type-hint]]# +- [[k9ox-difference-between-is-and]]# +- [[1zto-shallow-and-deep-copy]]# +- [[nfgb-slicing]]# +- [[adag-call-by-sharing]]# +- [[iexf-del]]# +- [[a8bt-high-order-functions]]# +- [[dcdy-callable-objects]]# +- [[135k-keyword-only-arguments]]