pycse - Beginner mode#

There are some concepts in Python that are tricky for beginners. pycse.beginner is a somewhat experimental package to eliminate some of these issues. I don’t actually use it a lot, and I am not sure it is better than taking time to learn it another way. It exists in pycse though, so I document it here.

from pycse.beginner import *
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 1
----> 1 from pycse.beginner import *

File /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/pycse/__init__.py:24
     12 from .PYCSE import (
     13     polyfit,
     14     regress,
   (...)
     20     lbic,
     21 )
     22 from .utils import feq, flt, fgt, fle, fge, read_gsheet
---> 24 from .hashcache import hashcache
     26 # from .beginner import *
     29 from IPython import get_ipython

File /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/pycse/hashcache.py:84
     82 import inspect
     83 import joblib
---> 84 import orjson
     85 import os
     86 from pathlib import Path

ModuleNotFoundError: No module named 'orjson'

Avoiding indexing in lists#

Indexing can be tricky at first. There is syntax you have to learn, and you have to get comfortably with the idea that indexing starts at 0 in Python.

This is not critical though, and there are functional approaches in pycse to avoid this and to use more natural names.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]

pycse.beginner defines functions for getting the first through fifth elements by name, and getting the nth element.

first(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[3], line 1
----> 1 first(a)

NameError: name 'first' is not defined
second(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 second(a)

NameError: name 'second' is not defined
third(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 third(a)

NameError: name 'third' is not defined
fourth(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 1
----> 1 fourth(a)

NameError: name 'fourth' is not defined
fifth(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[7], line 1
----> 1 fifth(a)

NameError: name 'fifth' is not defined

You can get the “nth” item, with the caveat that n starts at 0.

nth(a, 8)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[8], line 1
----> 1 nth(a, 8)

NameError: name 'nth' is not defined

functional approach to slicing#

You often want to “cut” a list, e.g. to get the list from some start position to stop position, optionally skipping items. Here we get the items from index=5 on. Remember that index=5 actually is the 6th position.

cut(a, 5)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[9], line 1
----> 1 cut(a, 5)

NameError: name 'cut' is not defined
# get index 5..7
# as with Python, the stop position is not inclusive. It means up to but not including the stop.
cut(a, start=5, stop=7)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[10], line 3
      1 # get index 5..7
      2 # as with Python, the stop position is not inclusive. It means up to but not including the stop.
----> 3 cut(a, start=5, stop=7)

NameError: name 'cut' is not defined
# get every other element starting at index=0
cut(a, step=2)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[11], line 2
      1 # get every other element starting at index=0
----> 2 cut(a, step=2)

NameError: name 'cut' is not defined

Other pieces of a list#

These functions are inspired by similar functions in the programming language lisp.

last(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 1
----> 1 last(a)

NameError: name 'last' is not defined
# everything past the first element
rest(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[13], line 2
      1 # everything past the first element
----> 2 rest(a)

NameError: name 'rest' is not defined
# everything but the last element
butlast(a)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[14], line 2
      1 # everything but the last element
----> 2 butlast(a)

NameError: name 'butlast' is not defined

More user-friendly functions#

Many numerical methods are not very user-friendly for new programmers. These functions provide (in my opinion) nicer user-interfaces.

A better fsolve#

Let us solve \(x^2 = -2.5\). This does not have a real answer. To solve this we have to create a function that will be zero, and use fsolve.

def f(x):
    return x**2 + 2.5

fsolve simply gives you a warning, and an answer that does not work.

from scipy.optimize import fsolve
fsolve(f, 2.5)
/tmp/ipykernel_2778/1685161423.py:2: RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last ten iterations.
  fsolve(f, 2.5)
array([-0.00090143])

nsolve actually raises an exception so you know it did not solve correctly.

nsolve(f, np.sqrt(2.5))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[17], line 1
----> 1 nsolve(f, np.sqrt(2.5))

NameError: name 'nsolve' is not defined

Simpler integration#

The quad function in scipy returns both the integral of a function and an estimated error. When you start out, this is more complex than preferred, so we change the behavior to only compute the integral, and to raise an exception if the result is not sufficiently accurate.

Here we evaluate \(\int_0^1 x^2 dx\).

def f(x):
    return x**2

integrate(f, 0, 1)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[18], line 4
      1 def f(x):
      2     return x**2
----> 4 integrate(f, 0, 1)

NameError: name 'integrate' is not defined