2024-heraklion-scientific-p.../notebooks/01a_Classes.ipynb

591 lines
11 KiB
Plaintext
Raw Permalink Normal View History

2024-08-27 14:52:41 +02:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"# The smell of classes"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## The \"data bundle\" smell"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:05:51.531289Z",
"start_time": "2018-07-27T17:05:51.526519+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"def momentum(mass, velocity):\n",
" return mass * velocity\n",
"\n",
"def energy(mass, velocity):\n",
" return 0.5 * mass * velocity ** 2\n",
"\n",
"def update_position(velocity, position, dt):\n",
" return position + velocity * dt"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:05:51.905235Z",
"start_time": "2018-07-27T17:05:51.900153+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9.0\n",
"1.2000000000000002\n",
"1.0\n"
]
}
],
"source": [
"# Naive\n",
"mass1 = 10.0\n",
"velocity1 = 0.9\n",
"\n",
"mass2 = 12.0\n",
"velocity2 = 0.1\n",
"\n",
"print(momentum(mass1, velocity1))\n",
"print(momentum(mass2, velocity2))\n",
"print(momentum(mass1, velocity2)) # ??"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"We have two parameters that will be sent to these functions over and over again: `mass` and `velocity`.\n",
"\n",
"Moreover, the parameters cannot be mixed up (e.g. the velocity of one particle with the mass of another)."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:05:52.116795Z",
"start_time": "2018-07-27T17:05:52.112569+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9.0\n",
"1.2000000000000002\n"
]
}
],
"source": [
"masses = [10.0, 12.0]\n",
"velocities = [0.9, 0.1]\n",
"\n",
"print(momentum(masses[0], velocities[0]))\n",
"print(momentum(masses[1], velocities[1]))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:05:52.548364Z",
"start_time": "2018-07-27T17:05:52.544726+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9.0\n",
"1.2000000000000002\n"
]
}
],
"source": [
"particle1 = {'mass': 10.0, 'velocity': 0.9}\n",
"particle2 = {'mass': 12.0, 'velocity': 0.1}\n",
"\n",
"print(momentum(particle1['mass'], particle1['velocity']))\n",
"print(momentum(particle2['mass'], particle2['velocity']))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"All of the functions above can be rewritten as a function of this particle \"instance\", eliminating the bookkeeping for the individual parameters."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:05:53.571400Z",
"start_time": "2018-07-27T17:05:53.567192+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9.0\n",
"1.2000000000000002\n"
]
}
],
"source": [
"def momentum(particle):\n",
" return particle['mass'] * particle['velocity']\n",
"\n",
"print(momentum(particle1))\n",
"print(momentum(particle2))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"An annoying thing of this solution is that we have to remember the name of the keys in the dictionary, and the solution is sensitive to typos.\n",
"\n",
"To solve this, we could write a function to build a particle, a.k.a a \"constructor\""
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:06:20.004037Z",
"start_time": "2018-07-27T17:06:19.998500+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9.0\n",
"1.2000000000000002\n"
]
}
],
"source": [
"def init_particle(mass, velocity):\n",
" self = {\n",
" 'mass': mass,\n",
" 'velocity': velocity\n",
" }\n",
" return self\n",
"\n",
"particle1 = init_particle(10.0, 0.9)\n",
"particle2 = init_particle(12.0, 0.1)\n",
"print(momentum(particle1))\n",
"print(momentum(particle2))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"`particle1` and `particle2` are called \"instances\" of the particle \"class\".\n",
"\n",
"Python classes are a way to formalize this pattern: creating a bundle of data that belongs together. E.g. the parameters of an experiment, the results of a simulation, etc."
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## Introducing classes as a data bundle template"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2018-08-04T13:04:49.208543Z",
"start_time": "2018-08-04T15:04:49.203180+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Particle:\n",
" def __init__(self, mass, velocity):\n",
" self.mass = mass\n",
" self.velocity = velocity\n",
"\n",
"particle1 = Particle(10.0, 0.9)\n",
"particle2 = Particle(12.0, 0.1)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:07:09.818544Z",
"start_time": "2018-07-27T17:07:09.814535+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0.9"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"particle1.velocity"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:07:09.997264Z",
"start_time": "2018-07-27T17:07:09.994114+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"text/plain": [
"12.0"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"particle2.mass"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T15:07:11.559629Z",
"start_time": "2018-07-27T17:07:11.555632+02:00"
},
"pycharm": {
"name": "#%%\n"
},
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'mass': 10.0, 'velocity': 0.9}"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"particle1.__dict__"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## Class methods"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2018-07-27T12:13:56.972938Z",
"start_time": "2018-07-27T14:13:56.969323+02:00"
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9.0\n",
"1.2000000000000002\n"
]
}
],
"source": [
"def momentum(particle):\n",
" return particle.mass * particle.velocity\n",
"\n",
"print(momentum(particle1))\n",
"print(momentum(particle2))"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9.0\n"
]
}
],
"source": [
"class Particle:\n",
" def __init__(self, mass, velocity):\n",
" self.mass = mass\n",
" self.velocity = velocity\n",
"\n",
" def momentum(self):\n",
" return self.mass * self.velocity\n",
"\n",
"particle1 = Particle(10.0, 0.9)\n",
"print(particle1.momentum())"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"We have been using class instances and methods all along..."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'A scanner darkly'"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s = 'A scanner Darkly'\n",
"s.capitalize()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'apple', 'banana', 'pineapple'}"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = set(['apple', 'banana', 'apple', 'pineapple'])\n",
"x"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'apple', 'banana', 'kiwi', 'pineapple'}"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x.union(['banana', 'kiwi'])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": []
}
],
"metadata": {
"hide_input": false,
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.3"
},
"toc": {
"nav_menu": {
"height": "174px",
"width": "252px"
},
"navigate_menu": true,
"number_sections": true,
"sideBar": true,
"threshold": 4,
"toc_cell": false,
"toc_position": {
"height": "953px",
"left": "0px",
"right": "1253px",
"top": "127px",
"width": "320px"
},
"toc_section_display": "block",
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}