Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: port entire Part 1 / Intro to Python #245

Merged
merged 15 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
339 changes: 176 additions & 163 deletions ch01python/00pythons.ipynb.py

Large diffs are not rendered by default.

262 changes: 114 additions & 148 deletions ch01python/015variables.ipynb.py

Large diffs are not rendered by default.

158 changes: 71 additions & 87 deletions ch01python/04functions.ipynb.py → ch01python/016functions.ipynb.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
# ---

# %% [markdown]
# ## Functions
# # Functions

# %% [markdown]
# ### Definition
# ## Definition

# %% [markdown]
#
Expand All @@ -28,100 +28,86 @@
def double(x):
return x * 2

print(double(5), double([5]), double('five'))

# %%
double(5)

# %%
double([5])

# %%
double("five")


# %% [markdown]
# ### Default Parameters
# ## Default Parameters

# %% [markdown]
# We can specify default values for parameters:

# %%
def jeeves(name = "Sir"):
return f"Very good, {name}"
def jeeves(name="Sir"):
return "Very good, " + name
Saransh-cpp marked this conversation as resolved.
Show resolved Hide resolved


# %%
jeeves()

# %%
jeeves('John')
jeeves("James")


# %% [markdown]
# If you have some parameters with defaults, and some without, those with defaults **must** go later.

# %% [markdown]
# If you have multiple default arguments, you can specify neither, one or both:

# %%
def jeeves(greeting="Very good", name="Sir"):
return f"{greeting}, {name}"
def product(x=5, y=7):
return x * y


# %%
jeeves()

# %%
jeeves("Hello")

# %%
jeeves(name = "John")
product(9)

# %%
jeeves(greeting="Suits you")
product(y=11)

# %%
jeeves("Hello", "Producer")
product()

dpshelio marked this conversation as resolved.
Show resolved Hide resolved

# %% [markdown]
# ### Side effects
# ## Side effects

# %% [markdown]
#
# Functions can do things to change their **mutable** arguments,
# so `return` is optional.
#
# This is pretty awful style, in general, functions should normally be side-effect free.
#
# Here is a contrived example of a function that makes plausible use of a side-effect
#
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll probably leave that as to warn about the following example. But it needs some explanation around it like:

# Note that the function below we are using `[:]`. This is used to update the content of the list, and though this function is not returning anything, it's changing the elements of the list.


# %%
def double_inplace(vec):
vec[:] = [element * 2 for element in vec]

z = list(range(4))

z = [1, 2, 3, 4]
Saransh-cpp marked this conversation as resolved.
Show resolved Hide resolved
double_inplace(z)
print(z)

# %%
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters[:] = []


# %% [markdown]
# In this example, we're using `[:]` to access into the same list, and write it's data.
Saransh-cpp marked this conversation as resolved.
Show resolved Hide resolved
#
# vec = [element*2 for element in vec]
# vec = [element * 2 for element in vec]
#
# would just move a local label, not change the input.
Saransh-cpp marked this conversation as resolved.
Show resolved Hide resolved

# %% [markdown]
# But I'd usually just write this as a function which **returned** the output:

# %%
def double(vec):
return [element * 2 for element in vec]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep this, but changed the first line as:

- # But I'd usually just write this as a function which **returned** the output:
+# A more common case would be to this as a function which **returned** the output:


# %% [markdown]
# Let's remind ourselves of the behaviour for modifying lists in-place using `[:]` with a simple array:
#
# Let's remind ourselves of this behaviour with a simple array:

# %%
x = 5
x = 7
x = ['a', 'b', 'c']
x = ["a", "b", "c"]
y = x

# %%
Expand All @@ -135,7 +121,21 @@ def double(vec):


# %% [markdown]
# ### Early Return
# ## Early Return

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a comment about it. Could you at least write a comment with a TODO?

# %%
def isbigger(x, limit=20):
if x > limit:
return True
print("Got here")
return False


isbigger(25, 15)

# %%
isbigger(40, 15)


# %% [markdown]
#
Expand All @@ -144,48 +144,46 @@ def double(vec):
#
#

# %% [markdown]
# Here's a slightly more plausibly useful function-with-side-effects to extend a list with a specified padding datum.

# %%
dpshelio marked this conversation as resolved.
Show resolved Hide resolved
def extend(to, vec, pad):
if len(vec) >= to:
return # Exit early, list is already long enough.

return
vec[:] = vec + [pad] * (to - len(vec))


# %%
x = list(range(3))
extend(6, x, 'a')
x = [1, 2, 3]
extend(6, x, "a")
print(x)

# %%
z = range(9)
extend(6, z, 'a')
z = list(range(9))
extend(6, z, "a")
print(z)


# %% [markdown]
# ### Unpacking arguments
# ## Unpacking arguments

# %% [markdown]
#
# If a vector is supplied to a function with a '*', its elements
# If a vector is supplied to a function with a `*`, its elements
# are used to fill each of a function's arguments.
#
#
#

# %%
def arrow(before, after):
return f"{before} -> {after}"
return str(before) + " -> " + str(after)
dpshelio marked this conversation as resolved.
Show resolved Hide resolved

arrow(1, 3)

print(arrow(1, 3))

# %%
x = [1, -1]
arrow(*x)

print(arrow(*x))

# %% [markdown]
#
Expand All @@ -198,17 +196,17 @@ def arrow(before, after):

# %%
charges = {"neutron": 0, "proton": 1, "electron": -1}

# %%
charges.items()

# %%
for particle in charges.items():
print(arrow(*particle))


# %% [markdown]
#
#
#

# %% [markdown]
# ### Sequence Arguments
# ## Sequence Arguments

# %% [markdown]
# Similiarly, if a `*` is used in the **definition** of a function, multiple
Expand All @@ -219,37 +217,23 @@ def doubler(*sequence):
return [x * 2 for x in sequence]


# %%
doubler(1, 2, 3)

# %%
doubler(5, 2, "Wow!")
print(doubler(1, 2, 3, "four"))


# %% [markdown]
# ### Keyword Arguments
# ## Keyword Arguments

# %% [markdown]
# If two asterisks are used, named arguments are supplied inside the function as a dictionary:
#
# If two asterisks are used, named arguments are supplied as a dictionary:
#
#
#

# %%
def arrowify(**args):
for key, value in args.items():
print(f"{key} -> {value}")

arrowify(neutron="n", proton="p", electron="e")
print(key + " -> " + value)
dpshelio marked this conversation as resolved.
Show resolved Hide resolved


# %% [markdown]
# These different approaches can be mixed:

# %%
def somefunc(a, b, *args, **kwargs):
print("A:", a)
print("B:", b)
print("args:", args)
print("keyword args", kwargs)


# %%
somefunc(1, 2, 3, 4, 5, fish="Haddock")
dpshelio marked this conversation as resolved.
Show resolved Hide resolved
arrowify(neutron="n", proton="p", electron="e")
Loading