Skip to content

Commit

Permalink
keyword, shallow, high order, call by sharing, laambda, del, is and =…
Browse files Browse the repository at this point in the history
…=, packages for functional
  • Loading branch information
FelipeMarcelino committed Jul 11, 2024
1 parent e49f4b0 commit d858370
Show file tree
Hide file tree
Showing 14 changed files with 304 additions and 3 deletions.
53 changes: 53 additions & 0 deletions 135k-keyword-only-arguments.md
Original file line number Diff line number Diff line change
@@ -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}</{name}>'
for c in content)
return '\n'.join(elements)
else:
return f'<{name}{attr_str} />'

>>> tag('br')
'<br />'
>>> tag('p', 'hello')
'<p>hello</p>'
>>> print(tag('p', 'hello', 'world'))
<p>hello</p>
<p>world</p>
>>> tag('p', 'hello', id=33)
'<p id="33">hello</p>'
>>> print(tag('p', 'hello', 'world', class_='sidebar'))
<p class="sidebar">hello</p>
<p class="sidebar">world</p>
>>> tag(content='testing', name="img")
'<img content="testing" />'
>>> my_tag = {'name': 'img', 'title': 'Sunset Boulevard',
... 'src': 'sunset.jpg', 'class': 'framed'}
>>> tag(**my_tag)
'<img class="framed" src="sunset.jpg" title="Sunset Boulevard" />'
```

- 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)
```
47 changes: 47 additions & 0 deletions 1zto-shallow-and-deep-copy.md
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion 38lz-zettelkasten.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
52 changes: 52 additions & 0 deletions 4fmy-packages-for-functional-programming-in-python.md
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions 82os-python-tuples.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]]#
Expand Down
2 changes: 1 addition & 1 deletion 8sjh-type-hint.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
- How is: `var_name: some_type` (PEP 484)

### References
Ramalho, 2022, p172-179
- Ramalho, 2022, p172-179
42 changes: 42 additions & 0 deletions a8bt-high-order-functions.md
Original file line number Diff line number Diff line change
@@ -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
<function factorial at 0x...>
>>> fact(5)
120
>>> map(factorial, range(11))
<map object at 0x...>
>>> 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
28 changes: 28 additions & 0 deletions adag-call-by-sharing.md
Original file line number Diff line number Diff line change
@@ -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
5 changes: 4 additions & 1 deletion aw9b-python-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
33 changes: 33 additions & 0 deletions dcdy-callable-objects.md
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions ey8t-lambda-function.md
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions iexf-del.md
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions k9ox-difference-between-is-and.md
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions tds4-python.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]]

0 comments on commit d858370

Please sign in to comment.