I don't like the code. My start point would be that
import pandas as pd
import numpy as np
if __name__ == "__main__":
n_samples = 10000
samples_np = pd.DataFrame(np.random.randint(1, 7, n_samples), columns=["face_value"])
print(samples_np.face_value.mean())
Speaking about abstraction, I don't know math, so first thought would be to look for *existing* abstractions. When I work with relational data, my first option to check is SQL. For math looks like DataFrame is a *standard* abstraction. To be fair, maybe first I would be using build-in `random.randin` I am not very familiar with `numpy`, but I would definitely google "pandas random sample", that would bring
https://pandas.pydata.org/docs/reference/api/pandas.DataFram... if __name__ == "__main__":
n_samples = 10000
sample_pd = pd.DataFrame({'face_value': [1, 2, 3, 4, 5, 6]})
print(sample_pd.sample(
n=n_samples,
replace=True,
random_state=np.random.bit_generator.randbits(20)).face_value.mean())
code uses lambda functions in some examples, it probably kills advantages of `numpy` performance. Using DataFrame API at least helps to avoid those pitfalls.
Type annotation, I like the idea, but in the end code looks like Java, but doesn't performs like Java. It is very hard to make it right in Python, also some of them wrong.
(
@dataclass(frozen=True): - don't need ":"
Gaussian.sample - missing return )
when return added it doesn't return `-> Sequence[float]:`
Gaussian().sample(90).dtype
>>> dtype('float64')
-> Sequence[Union(numpy.float64, numpy.float32, numpy.float16)]: # ?
I don't believe "scientific code" is fundamentally different from any other code, I would go with following normal development practices
1) review design ("don't reinvent wheel")
2) add tests
3) make code review
4) version control
etc.