Obsah
1. Numscrypt aneb Numpy běžící ve webovém prohlížeči
3. Instalace knihovny Numscrypt
4. Příprava projektu pro otestování možností Numscryptu
5. Problematika importu „správného“ balíčku Numpy
6. Import různých balíčků pro CPython a pro Transcrypt
7. Výsledek transpřekladu do JavaScriptu
8. Tisk obsahu pole na konzoli webového prohlížeče
9. Tisk obsahu pole přímo na webovou stránku
10. Specifikace typu prvků pole
11. Konstrukce dvourozměrného pole
12. Konstruktor numpy.zeros a numpy.ones
13. Konstruktor jednotkové matice
16. Sčítání, odčítání a násobení matic
18. Repositář s demonstračními příklady Numscryptu
19. Repositář s demonstračními příklady Transcryptu
1. Numscrypt aneb Numpy běžící ve webovém prohlížeči
S projektem Transcrypt popsaným na začátku týdne je velmi úzce spojen projekt nazvaný Numscrypt (psaný též Nµmscrλpt). Jedná se o částečnou portaci známé knihovny Numpy do JavaScriptu, takže funkce a přetížené operátory z Numpy je možné využít v Pythonních skriptech transpilovaných do JavaScriptu. Interně je Numscrypt založen na typovaných polích JavaScriptu, což na jednu stranu zajišťuje velmi rychlé operace, na stranu druhou je však dimenze polí omezena na 1 či 2 (vektory, matice) a navíc prvky polí mohou být pouze typu int32, float32, float64, complex32 a complex64. Taktéž je (prozatím) omezeno množství funkcí, které jsou v Numscryptu definovány. A navíc – práce s přetíženými operátory není příliš přímočará – viz též šestnáctou kapitolu. Dnešní článek tak bude hledat odpověď na otázku, zda se jedná o slepou cestu či nikoli.
2. Numpy vs. Numscrypt
Numpy a Numscrypt mají některé společné vlastnosti a některé (zásadní) rozdíly.
Funkce a objekty nabízené knihovnou Numpy se sice volají přímo z Pythonu, ve skutečnosti se však interní datové struktury dosti podstatným způsobem odlišují od datových struktur využívaných samotným Pythonem. V knihovně Numpy tvoří základ datová struktura nazvaná ndarray, která reprezentuje pole o prakticky libovolném počtu dimenzí (ostatně ono „nd“ ve jménu „ndarray“ značí N-dimensional). Tato pole se liší od běžných seznamů či n-tic v Pythonu, protože ndarray jsou homogenní datovou strukturou: všechny prvky totiž mají shodný typ a navíc všechny prvky leží za sebou, zatímco seznamy v Pythonu jsou měnitelné (prvky lze přidávat a odebírat) a obecně nehomogenní (každý prvek může mít odlišný datový typ). Za tuto velkou flexibilitu se samozřejmě platí, a to jak většími nároky na operační paměť (reference na objekty), tak i pomalejším zpracováním.
V Numscryptu jsou pole realizována formou JavaScriptových polí s jednou či dvěma dimenzemi. Jde tedy, jak již víme, o typovaná pole s omezenou množinou typů prvků pole. Opět se tedy jedná o homogenní datové struktury s neměnitelným tvarem (z tohoto pohledu jsou perzistentní). Kvůli zcela odlišné implementaci není možné jednoduše měnit tvar pole – operace reshape tedy prozatím není dostupná.
3. Příprava projektu pro otestování možností Numscryptu
Instalace Numscryptu probíhá, resp. přesněji řečeno může probíhat podobně jako instalace Transcryptu (ve skutečnosti je nutné nainstalovat oba zmíněné balíčky). Instalaci tedy můžeme provést například s využitím standardního nástroje pip, který již velmi dobře známe. Instalace pouze pro aktuálně přihlášeného uživatele vypadá takto:
$ pip3 install --user transcrypt numscrypt Collecting transcrypt Downloading Transcrypt-3.9.1-py2.py3-none-any.whl (19.0 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 19.0/19.0 MB 3.0 MB/s eta 0:00:00 Collecting numscrypt Downloading Numscrypt-0.0.40.tar.gz (4.7 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.7/4.7 MB 5.0 MB/s eta 0:00:00 Preparing metadata (setup.py) ... done Requirement already satisfied: mypy in /usr/local/lib64/python3.11/site-packages (from transcrypt) (1.6.1) Requirement already satisfied: typing-extensions>=4.1.0 in /usr/local/lib/python3.11/site-packages (from mypy->transcrypt) (4.8.0) Requirement already satisfied: mypy-extensions>=1.0.0 in /usr/local/lib/python3.11/site-packages (from mypy->transcrypt) (1.0.0) Installing collected packages: transcrypt, numscrypt DEPRECATION: numscrypt is being installed using the legacy 'setup.py install' method, because it does not have a 'pyproject.toml' and the 'wheel' package is not installed. pip 23.1 will enforce this behaviour change. A possible replacement is to enable the '--use-pep517' option. Discussion can be found at https://github.com/pypa/pip/issues/8559 Running setup.py install for numscrypt ... done Successfully installed numscrypt-0.0.40 transcrypt-3.9.1
4. Příprava projektu pro otestování možností Numscryptu
Transcrypt i Numscrypt je možné nastavit i jako závislý balíček (přímá závislost, popř. vývojová závislost) při použití nástroje PDM, který byl na Rootu popsán minulý týden. Ukažme si pro úplnost, jak by mohl vypadat projekt, který je na Transcryptu a na knihovně Numscrypt postaven.
Nejprve si necháme vytvořit kostru nového projektu (prozatím bez závislostí):
$ pdm init
Poctivě odpovíme na položené otázky (většinou jen potvrzením klávesou Enter, další odpovědi jsou označeny tučně):
Creating a pyproject.toml for PDM... Please enter the Python interpreter to use 0. /usr/bin/python (3.11) 1. /usr/bin/python3.11 (3.11) 2. /usr/bin/python3 (3.11) Please select (0): 0 Would you like to create a virtualenv with /usr/bin/python? [y/n] (y): y Virtualenv is created successfully at /home/ptisnovs/test2/.venv Is the project a library that is installable? If yes, we will need to ask a few more questions to include the project name and build backend [y/n] (n): n License(SPDX name) (MIT): Author name (): Pavel Tisnovsky Author email (): tisnik@nowhere.us Python requires('*' to allow any) (>=3.11): Project is initialized successfully
Do právě vzniklého projektu ve druhém kroku přidáme závislost na Transcryptu (navíc s přepínačem -d, protože se jedná o závislost pro vývojáře):
$ pdm add -d transcrypt
V tomto kroku by se měly nainstalovat stejné balíčky, jako při instalaci přes pip (viz předchozí kapitolu):
Adding group dev to lockfile Adding packages to dev dev-dependencies: transcrypt 🔒 Lock successful Changes are written to pyproject.toml. Synchronizing working set with resolved packages: 4 to add, 0 to update, 0 to remove ✔ Install mypy-extensions 1.0.0 successful ✔ Install typing-extensions 4.8.0 successful ✔ Install transcrypt 3.9.1 successful ✔ Install mypy 1.6.1 successful 🎉 All complete!
Navíc ve třetím kroku přidáme i knihovnu Numscrypt, a to naprosto stejným příkazem (balíček pro vývojáře):
$ pdm add -d numscrypt
Průběh instalace:
Adding packages to dev dev-dependencies: numscrypt 🔒 Lock successful Changes are written to pyproject.toml. Synchronizing working set with resolved packages: 1 to add, 0 to update, 0 to remove ✔ Install numscrypt 0.0.40 successful 🎉 All complete!
Výsledný projektový soubor, který se jmenuje project.toml, by měl vypadat následovně (obsahuje všechny přímé závislosti, ale ne již tranzitivní závislosti):
[project] name = "" version = "" description = "" authors = [ {name = "Pavel Tisnovsky", email = "tisnik@nowhere.us"}, ] dependencies = [] requires-python = ">=3.11" readme = "README.md" license = {text = "MIT"} [tool.pdm.dev-dependencies] dev = [ "transcrypt>=3.9.1", "numscrypt>=0.0.40", ]
Pro úplnost si taktéž ukažme lock file, který obsahuje jak přímé závislosti, tak i závislosti nepřímé:
# This file is @generated by PDM. # It is not intended for manual editing. [metadata] groups = ["default", "dev"] cross_platform = true static_urls = false lock_version = "4.3" content_hash = "sha256:4d013d66c37e565481b0e84339bbabab4630036b0845805982beb532561f4ee5" [[package]] name = "mypy" version = "1.6.1" requires_python = ">=3.8" summary = "Optional static typing for Python" dependencies = [ "mypy-extensions>=1.0.0", "typing-extensions>=4.1.0", ] files = [ {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, ] [[package]] name = "mypy-extensions" version = "1.0.0" requires_python = ">=3.5" summary = "Type system extensions for programs checked with the mypy type checker." files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] name = "numscrypt" version = "0.0.40" summary = "A tiny bit of NumPy for Transcrypt using JavaScript typed arrays" dependencies = [ "transcrypt", ] files = [ {file = "Numscrypt-0.0.40.tar.gz", hash = "sha256:427e5730707f246058993662b28410e0862ba79bb72126aeae5f5d423823f40d"}, ] [[package]] name = "transcrypt" version = "3.9.1" summary = "Python to JavaScript transpiler, supporting multiple inheritance and generating lean, highly readable code" dependencies = [ "mypy", ] files = [ {file = "Transcrypt-3.9.1-py2.py3-none-any.whl", hash = "sha256:73f5b3587f561aff66fa82f5fb3407f8b5950e991ad335f5f6dd889990ab0e10"}, ] [[package]] name = "typing-extensions" version = "4.8.0" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" files = [ {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, ]
5. Problematika importu „správného“ balíčku Numpy
Pokusme se nyní (trans)přeložit následující skript, který je naprosto legální a v případě, že použijeme CPython a knihovnu Numpy, tak skutečně zkonstruuje jednorozměrné pole a následně ho vypíše na terminál:
# Knihovna Numpy a Numscrypt # # Konstrukce jednorozměrného pole konstruktorem numpy.array() # # vytvoření pole se čtyřmi prvky # import hlavního balíčku knihovny Numpy import numpy # konstrukce pole a = numpy.array([1, 2, 3, 4]) # tisk obsahu pole na standardní výstup print(a)
Transpřeklad se spustí tímto příkazem (přepínač -n zakazuje optimalizace):
$ pdm run transcrypt -n 01_array.py
Jak je z následujícího výpisu patrné, nebude transpřeklad úspěšný, protože se nenalezne soubor numpy.py ani soubor numpy.js v žádném z adresářů, z nichž lze import provést:
Transcrypt (TM) Python to JavaScript Small Sane Subset Transpiler Version 3.9.0 Copyright (C) Geatec Engineering. License: Apache 2.0 Saving target code in: /home/ptisnovs/test2/__target__/org.transcrypt.__runtime__.js Error while compiling (offending file last): File '01_array', line 6, namely: Import error, can't find any of: /home/ptisnovs/test2/numpy.py /home/ptisnovs/test2/numpy.js /home/ptisnovs/test2/.venv/lib/python3.11/site-packages/transcrypt/modules/numpy.py /home/ptisnovs/test2/.venv/lib/python3.11/site-packages/transcrypt/modules/numpy.js /home/ptisnovs/test2/.venv/bin/numpy.py /home/ptisnovs/test2/.venv/bin/numpy.js /usr/lib64/python3.11/numpy.py /usr/lib64/python3.11/numpy.js /usr/lib64/python3.11/lib-dynload/numpy.py /usr/lib64/python3.11/lib-dynload/numpy.js /home/ptisnovs/test2/.venv/lib64/python3.11/site-packages/numpy.py /home/ptisnovs/test2/.venv/lib64/python3.11/site-packages/numpy.js /home/ptisnovs/test2/.venv/lib/python3.11/site-packages/numpy.py /home/ptisnovs/test2/.venv/lib/python3.11/site-packages/numpy.js Aborted
6. Import různých balíčků pro CPython a pro Transcrypt
Jak je však možné přímo v Pythonovském skriptu rozlišit, zda je skript spuštěn ve standardním CPythonu či zda byl transpřeložen (či je transpřekládán) do JavaScriptu? Protože právě na tom, jaká operace je prováděna, závisí, který balíček budeme chtít naimportovat – zda numpy nebo numscrypt.
Ideální a čitelné řešení v tomto případě (prozatím) neexistuje, ovšem můžeme použít tento trik – zkontrolujeme jméno nástroje, který skript zpracovává. Jedná se ovšem o dosti nestandardní konstrukci:
from org.transcrypt.stubs.browser import __envir__ if __envir__.executor_name == __envir__.transpiler_name: import numscrypt as np
Import standardní knihovny Numpy bude „obalen“ do pseudofunkcí __pragma__. Jejich zápis sice skutečně odpovídá volání běžných funkcí, ale ve skutečnosti jsou vyhodnocovány již v době transpřekladu:
__pragma__ ('skip') import numpy as np __pragma__ ('noskip')
Výsledný skript by měl nyní vypadat následovně:
# Knihovna Numpy a Numscrypt # # Konstrukce jednorozměrného pole konstruktorem numpy.array() # # vytvoření pole se čtyřmi prvky from org.transcrypt.stubs.browser import __envir__ # import hlavního balíčku knihovny Numpy if __envir__.executor_name == __envir__.transpiler_name: import numscrypt as np # import pro CPython __pragma__ ('skip') import numpy as np __pragma__ ('noskip') # konstrukce pole a = np.array([1, 2, 3, 4]) # tisk obsahu pole na standardní výstup print(a)
7. Výsledek transpřekladu do JavaScriptu
Pro zajímavost se podívejme na výsledek překladu (transpřekladu) do JavaScriptu. Jedná se o přímočarou a dobře čitelnou transformaci kódu, která je zvláštní pouze „vytažením“ příkazu pro import balíčku z podmínky:
// Transcrypt'ed from Python, 2023-10-25 10:11:33 import {AssertionError, AttributeError, BaseException, DeprecationWarning, Exception, IndexError, IterableError, KeyError, NotImplementedError, RuntimeWarning, StopIteration, UserWarning, ValueError, Warning, __JsIterator__, __PyIterator__, __Terminal__, __add__, __and__, __call__, __class__, __envir__, __eq__, __floordiv__, __ge__, __get__, __getcm__, __getitem__, __getslice__, __getsm__, __gt__, __i__, __iadd__, __iand__, __idiv__, __ijsmod__, __ilshift__, __imatmul__, __imod__, __imul__, __in__, __init__, __ior__, __ipow__, __irshift__, __isub__, __ixor__, __jsUsePyNext__, __jsmod__, __k__, __kwargtrans__, __le__, __lshift__, __lt__, __matmul__, __mergefields__, __mergekwargtrans__, __mod__, __mul__, __ne__, __neg__, __nest__, __or__, __pow__, __pragma__, __pyUseJsNext__, __rshift__, __setitem__, __setproperty__, __setslice__, __sort__, __specialattrib__, __sub__, __super__, __t__, __terminal__, __truediv__, __withblock__, __xor__, abs, all, any, assert, bool, bytearray, bytes, callable, chr, copy, deepcopy, delattr, dict, dir, divmod, enumerate, filter, float, getattr, hasattr, input, int, isinstance, issubclass, len, list, map, max, min, object, ord, pow, print, property, py_TypeError, py_iter, py_metatype, py_next, py_reversed, py_typeof, range, repr, round, set, setattr, sorted, str, sum, tuple, zip} from './org.transcrypt.__runtime__.js'; import * as np from './numscrypt.js'; var __name__ = '__main__'; if (__envir__.executor_name == __envir__.transpiler_name) { } export var a = np.array ([1, 2, 3, 4]); print (a); //# sourceMappingURL=02_array.map
8. Tisk obsahu pole na konzoli webového prohlížeče
V Pythonním skriptu jsme pole vytiskli standardní funkcí print. Pokud přeložíme takový program do JavaScriptu, bude print (tentokrát její JavaScriptová varianta) provádět tisk na konzoli webového prohlížeče (ve Firefoxu lze zobrazit přes Ctrl+Shift+K):
# Knihovna Numpy a Numscrypt # # Konstrukce jednorozměrného pole konstruktorem numpy.array() # # vytvoření pole se čtyřmi prvky # import hlavního balíčku knihovny Numpy if __envir__.executor_name == __envir__.transpiler_name: import numscrypt as np # import pro CPython __pragma__ ('skip') import numpy as np __pragma__ ('noskip') # konstrukce pole a = np.array([1, 2, 3, 4]) # tisk obsahu pole na standardní výstup print(a)
Transpřeložený skript lze na HTML stránku načíst následujícím způsobem:
<html> <head> <title>Numscrypt demo</title> </head> <body> <h2>Numscrypt demo</h2> <script type="module">import * as numpy_demo from './__target__/03_array_web.js';</script> </body> </html>
$ python3 -m http.server
Výsledek by měl vypadat následovně:
Obrázek 1: Konzole prohlížeče se zobrazeným polem.
9. Tisk obsahu pole přímo na webovou stránku
Samozřejmě nám nic nebráni v tom, abychom si pole (resp. přesněji řečeno jeho prvky) nechali vytisknout přímo na webovou stránku. Náš skript nepatrně upravíme tak, aby pole zapsal do zvoleného HTML elementu na stránce, což je triviální:
# Knihovna Numpy a Numscrypt # # Konstrukce jednorozměrného pole konstruktorem numpy.array() # # vytvoření pole se čtyřmi prvky # import hlavního balíčku knihovny Numpy if __envir__.executor_name == __envir__.transpiler_name: import numscrypt as np # import pro CPython __pragma__ ('skip') import numpy as np __pragma__ ('noskip') def construct_array(): # konstrukce pole a = np.array([1, 2, 3, 4]) # tisk obsahu pole na webovou stránku document.getElementById("output").innerHTML = str(a) construct_array()
Následně nám postačí si webovou stránku upravit – přidat si do ní vhodný HTML element s ID nastaveným na output:
<html> <head> <title>Numscrypt demo</title> </head> <body> <h2>Numscrypt demo</h2> <pre id="output" style="font-size:300%; background-color:#ffffc0; padding:5px;"> </pre> <script type="module">import * as numpy_demo from './__target__/04_array_web.js';</script> </body> </html>
Výsledek by měl vypadat následovně:
Obrázek 2: HTML stránka se zobrazeným polem.
10. Specifikace typu prvků pole
Při vytváření polí typu ndarray v Numpy, ať již se jedná o vektory, matice či o pole s větším množstvím dimenzí, lze specifikovat datový typ všech prvků a dokonce i uspořádání prvků v paměti (buď podle zvyklostí jazyka Fortran nebo jazyka C). V knihovně Numscrypt jsme omezeni pouze na pět datových typů prvků:
- int32
- float32
- float64
- complex32
- complex64
To by mělo pro některé účely plně postačovat, na druhé straně nastanou problémy při zpracování zvukových a obrazových dat.
Podívejme se nyní na to, jak lze specifikovat datový typ prvků pole na float32:
# Knihovna Numpy a Numscrypt # # Konstrukce jednorozměrného pole konstruktorem numpy.array() # # explicitní specifikace typu všech prvků pole # (interně se provádí přetypování) # import hlavního balíčku knihovny Numpy if __envir__.executor_name == __envir__.transpiler_name: import numscrypt as np # import pro CPython __pragma__ ('skip') import numpy as np __pragma__ ('noskip') def construct_array(): # konstrukce pole a = np.array(range(10), dtype=np.float) # tisk obsahu pole na webovou stránku document.getElementById("output").innerHTML = str(a) construct_array()
11. Konstrukce dvourozměrného pole
Základem konstrukce dvourozměrného pole (podporovaného v Numscryptu) je předání hodnot prvků formou seznamu seznamů, seznamu n-tic atd. Je to ukázáno na dalším příkladu. Tvar pole je odvozen na základě předaných dat:
# Knihovna Numpy # # Příklady použití funkce numpy.array # # vytvoření dvourozměrné matice # import hlavního balíčku knihovny Numpy if __envir__.executor_name == __envir__.transpiler_name: import numscrypt as np # import pro CPython __pragma__ ('skip') import numpy as np __pragma__ ('noskip') # konstrukce pole a = np.array([[1, 2, 3], [4, 5, 6]]) # tisk obsahu pole na standardní výstup print(a)
12. Konstruktor numpy.zeros a numpy.ones
Kromě funkce numpy.array se poměrně často setkáme s nutností vytvořit vektor či matici s nulovými prvky. V tomto případě samozřejmě není nutné složitě vytvářet a předávat takové pole do funkce numpy.array, ale lze namísto toho využít funkci nazvanou numpy.zeros, což je rychlejší i méně paměťově náročnější. Té se předá n-tice (musí se skutečně jednat o n-tici, nikoli o seznam parametrů, proto nezapomeňte na závorky) specifikující dimenzi vektoru, matice či N-dimenzionálního pole. Stejné konstruktory nalezneme i v Numscryptu.
Konstrukce jednorozměrného pole neboli vektoru:
# konstrukce pole a = np.zeros((10,)) # tisk obsahu pole na standardní výstup print(a)
Konstrukce dvojrozměrného pole neboli matice:
# konstrukce pole a = np.zeros((5, 5)) # tisk obsahu pole na standardní výstup print(a)
Dalším velmi často používaným typem vektoru či matice je taková struktura, jejíž všechny prvky mají hodnotu 1. Takový vektor. popř. matice. je možné vytvořit funkcí numpy.ones.
Konstrukce jednorozměrného pole neboli vektoru:
# konstrukce pole a = np.ones((10,)) # tisk obsahu pole na standardní výstup print(a)
Konstrukce dvojrozměrného pole neboli matice:
# konstrukce pole a = np.ones((3, 4)) # tisk obsahu pole na standardní výstup print(a)
# import hlavního balíčku knihovny Numpy if __envir__.executor_name == __envir__.transpiler_name: import numscrypt as np # import pro CPython __pragma__ ('skip') import numpy as np __pragma__ ('noskip')
13. Konstruktor jednotkové matice
Pro konstrukci jednotkové matice lze využít konstruktor np.identity, nikoli však np.eye, který sice existuje v Numpy, ale nikoli v Numscryptu. Jednotkovou matici o velikosti 10×10 prvků sestrojíme takto:
# konstrukce pole a = np.identity(10) # tisk obsahu pole na standardní výstup print(a)
14. Indexování prvků polí
Jakým způsobem se pole s využitím knihovny Numpy i Numscrypt vytváří již víme. Ještě si však musíme říct, jak se prvky uložené v polích vybírají neboli indexují. V případě jednorozměrných polí je to ve skutečnosti velmi jednoduché – prvky jsou totiž číslovány od nuly a díky přetížení operátoru [] (operátor indexování) je možné prvky v případě potřeby indexovat i od konce pole. V tomto případě se musí použít záporné číslo, takže a[1] značí druhý prvek pole zatímco a[-1] první prvek od konce:
# jednorozměrná pole - vektory a = np.array([1,2,3,4,5,6,7,8,9,10]) # tisk původního pole print(a) # indexování prvků od nuly print(a[0]) # indexování prvků od nuly print(a[5]) # indexovat lze i od konce pole print(a[-1]) # indexovat lze i od konce pole print(a[-5])
U dvourozměrných polí je situace poněkud komplikovanější, neboť v tomto případě je nutné použít dva či větší počet indexů (jeden index pro každou dimenzi). Vzhledem k tomu, že v různých programovacích jazycích a rozličných specializovaných nástrojích typu R či Matlab, se používají odlišné způsoby zápisu více indexů, podporuje knihovna Numpy (i Numscrypt) dva způsoby zápisu – buď se všechny indexy oddělí čárkou a vloží se do jediného bloku omezeného hranatými závorkami [], nebo se alternativně pro každou dimenzi použije zvláštní hranatá závorka (syntaxe odvozená od Céčka):
# dvourozměrná pole - matice a = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]]) # tisk původního pole print(a) # přístup k prvkům: řádek/sloupec print(a[0][2]) # přístup k prvkům: řádek/sloupec print(a[2][0])
15. Vytváření „řezů“ z polí
V mnoha případech je nutné z polí získat hodnoty většího množství prvků tvořících souvislý blok. Může se například jednat o všechny prvky pole kromě prvku prvního a posledního (typické pro některé filtry), prvky z první poloviny pole atd. I v tomto případě knihovna Numpy (a taktéž Numscrypt) nabízí vývojářům velmi elegantní řešení, a to ve formě takzvaných řezů (slices). Namísto jediného indexu je totiž možné zadat dva indexy oddělené dvojtečkou, které potom reprezentují začátek a konec řezu:
# původní pole a = np.array([1,2,3,4,5,6,7,8,9,10]) # tisk původního pole print(a) # slicing b = a[3:7] # tisk nového pole print(b)
16. Sčítání, odčítání a násobení matic
V případě, že uživatel vytvoří matice o stejné velikosti, lze takové matice sčítat či odčítat. Pokud se k matici přičte či odečte skalární hodnota (matice+10, matice-42), jedná se o operaci prováděnou s každým prvkem matice zvlášť (sčítají se prvky se shodným indexem či indexy).
Zaměřme se nyní pouze na součet matic. V knihovně Numpy lze realizovat velmi snadno:
# dvourozměrná pole - matice a = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10],[11,12,13,14]]) b = np.identity(4) # tisk původního pole print(a) # tisk původního pole print(b) # operace nad celou maticí c = a + b print(c)
Ovšem takto zapsaný skript není plně kompatibilní s Numscryptem! (předpokládám že proto, že na úrovni AST chybí příslušné metainformace). Z tohoto důvodu je nutné postupovat nepatrně odlišně – použít pseudofunkci „__pragma__“, s níž jsme se již setkali. Tentokráte jí předáme parametr „opov“ a „noopov“:
# dvourozměrná pole - matice a = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10],[11,12,13,14]]) b = np.identity(4) # tisk původního pole print(a) # tisk původního pole print(b) # operace nad celou maticí __pragma__ ('opov') c = a + b __pragma__ ('noopov') print(c)
17. Závěrečné zhodnocení
Projekt Numscrypt je postaven na zajímavé myšlence, která si zaslouží další vývoj, ovšem v současnosti se podle mého názoru v žádném případě nejedná o plnohodnotnou náhradu například za Pyscript, který podporuje celé Numpy (tento projekt je založen na odlišném principu, ale cíle jsou totožné – umožnit použití Pythonu a Numpy na straně webového klienta). Ostatně i verze Numscryptu naznačuje, že se prozatím nejedná o stabilní produkt, takže jeho reálné nasazení je v současnosti spíše cestou k mnoha problémům; navíc je nutné stávající skripty ručně upravovat.
18. Repositář s demonstračními příklady Numscryptu
19. Repositář s demonstračními příklady Transcryptu
V této kapitole jsou uvedeny odkazy na skripty, s nimiž jsme se seznámili při popisu nástroje Transcrypt v tomto článku:
20. Odkazy na Internetu
- Numscrypt: A tiny bit of NumPy for Transcrypt, using JavaScript typed arrays
https://www.transcrypt.org/numscrypt/numscrypt.html - Dokumentace k projektu Numscrypt
https://www.transcrypt.org/numscrypt/docs/html/index.html - Stránky projektu Transcrypt
https://www.transcrypt.org/ - Balíček Transcrypt na PyPi
https://pypi.org/project/Transcrypt/ - Transcrypt na GitHubu
https://github.com/TranscryptOrg/Transcrypt - Transcrypt: getting started
https://www.transcrypt.org/docs/html/installation_use.html - Google Closure Compiler
https://github.com/google/closure-compiler - Statické typové kontroly zdrojových kódů Pythonu prováděné nástrojem Mypy
https://www.root.cz/clanky/staticke-typove-kontroly-zdrojovych-kodu-pythonu-provadene-nastrojem-mypy/ - Statické typové kontroly zdrojových kódů Pythonu prováděné nástrojem Mypy (2.část)
https://www.root.cz/clanky/staticke-typove-kontroly-zdrojovych-kodu-pythonu-provadene-nastrojem-mypy-2-cast/ - Statické typové kontroly zdrojových kódů Pythonu prováděné nástrojem Mypy (3)
https://www.root.cz/clanky/staticke-typove-kontroly-zdrojovych-kodu-pythonu-provadene-nastrojem-mypy-3/ - PyScript
https://pyscript.net/ - PyScript na GitHubu
https://github.com/pyscript/pyscript - Getting started with PyScript
https://github.com/pyscript/pyscript/blob/main/docs/tutorials/getting-started.md - PyScript examples
https://github.com/pyscript/pyscript/tree/main/examples - What is PyScript
https://docs.pyscript.net/latest/concepts/what-is-pyscript.html - Pyodide
https://pyodide.org/en/stable/ - PyScript: JavaScript and Python Interoperability
https://www.jhanley.com/blog/pyscript-javascript-and-python-interoperability/ - Pyscript: JavaScript Event Callbacks
https://www.jhanley.com/blog/pyscript-javascript-callbacks/ - Compiling to WebAssembly: It’s Happening!
https://hacks.mozilla.org/2015/12/compiling-to-webassembly-its-happening/ - WebAssembly
https://webassembly.org/ - Blogy o WASM a Emscripten
https://www.jamesfmackenzie.com/sitemap/#emscripten - wat2wasm demo
https://webassembly.github.io/wabt/demo/wat2wasm/ - WABT: The WebAssembly Binary Toolkit
https://github.com/WebAssembly/wabt - Programming using Web Assembly
https://medium.com/@alexc73/programming-using-web-assembly-c4c73a4e09a9 - Experiments with image manipulation in WASM using Go
https://agniva.me/wasm/2018/06/18/shimmer-wasm.html - Fable
https://fable.io/ - Využití WebAssembly z programovacího jazyka Go
https://www.root.cz/clanky/vyuziti-webassembly-z-programovaciho-jazyka-go/ - WebAssembly prošlo standardizací ve W3C, byla vydána verze 1.0
https://www.root.cz/zpravicky/webassembly-proslo-standardizaci-ve-w3c-byla-vydana-verze-1–0/ - WebAssembly na Wiki Golangu
https://github.com/golang/go/wiki/WebAssembly - The future of WebAssembly – A look at upcoming features and proposals
https://blog.scottlogic.com/2018/07/20/wasm-future.html - Writing WebAssembly By Hand
https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html - WebAssembly Specification
https://webassembly.github.io/spec/core/index.html - Index of Instructions
https://webassembly.github.io/spec/core/appendix/index-instructions.html - The WebAssembly Binary Toolkit
https://github.com/WebAssembly/wabt - Will WebAssembly replace JavaScript? Or Will WASM Make JavaScript More Valuable in Future?
https://dev.to/vaibhavshah/will-webassembly-replace-javascript-or-will-wasm-make-javascript-more-valuable-in-future-5c6e - Roadmap (pro WebAssemly)
https://webassembly.org/roadmap/ - S-expression
https://en.wikipedia.org/wiki/S-expression - Understanding WebAssembly text format
https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format - Learning Golang through WebAssembly – Part 1, Introduction and setup
https://www.aaron-powell.com/posts/2019–02–04-golang-wasm-1-introduction/ - Learning Golang through WebAssembly – Part 2, Writing your first piece of Go
https://www.aaron-powell.com/posts/2019–02–05-golang-wasm-2-writing-go/ - Learning Golang through WebAssembly – Part 3, Interacting with JavaScript from Go
https://www.aaron-powell.com/posts/2019–02–06-golang-wasm-3-interacting-with-js-from-go/ - Golang webassembly (wasm) testing with examples
https://jelinden.fi/blog/golang-webassembly-wasm-testing-with-examples/qB7Tb2KmR - Use Cases (of WebAssembly)
https://webassembly.org/docs/use-cases/ - JupyterLite na PyPi
https://pypi.org/project/jupyterlite/ - JupyterLite na GitHubu
https://github.com/jupyterlite/jupyterlite - Dokumentace k projektu JupyterLite
https://github.com/jupyterlite/jupyterlite - A quick guide about Python implementations
https://blog.rmotr.com/a-quick-guide-about-python-implementations-aa224109f321 - How Brython works
https://github.com/brython-dev/brython/wiki/How%20Brython%20works - Brython – A Python 3 implementation for client-side web programming
http://www.brython.info/ - Brython videos and talks
https://github.com/brython-dev/brython/wiki/Brython-videos-and-talks - What is Brython?
https://medium.com/frontendweb/what-is-brython-6edb424b07f6 - Python in browser (tabulka s porovnáními)
http://stromberg.dnsalias.org/~strombrg/pybrowser/python-browser.html - JavaScript is Assembly Language for the Web: Sematic Markup is Dead! Clean vs. Machine-coded HTML
http://www.hanselman.com/blog/JavaScriptIsAssemblyLanguageForTheWebSematicMarkupIsDeadCleanVsMachinecodedHTML.aspx - pyscript VS brython
https://www.libhunt.com/compare-pyscript-vs-brython - PyScript – Run Python in the Browser! THE END of JavaScript???
https://www.youtube.com/watch?v=du8vQC44PC4 - PyScript is Python in Your Browser
https://www.youtube.com/watch?v=MJvCeKwr4z4 - JupyterLite na PyPi
https://pypi.org/project/jupyterlite/ - JupyterLite na GitHubu
https://github.com/jupyterlite/jupyterlite - Dokumentace k projektu JupyterLite
https://github.com/jupyterlite/jupyterlite - Matplotlib Home Page
http://matplotlib.org/ - Matplotlib (Wikipedia)
https://en.wikipedia.org/wiki/Matplotlib - Popis barvových map modulu matplotlib.cm
https://gist.github.com/endolith/2719900#id7 - Ukázky (palety) barvových map modulu matplotlib.cm
http://matplotlib.org/examples/color/colormaps_reference.html - Galerie grafů vytvořených v Matplotlibu
https://matplotlib.org/3.2.1/gallery/ - Replacing Javascript with Python
https://stackoverflow.com/questions/69510962/replacing-javascript-with-python - Can Python Replace Javascript in the Future?
https://dev.to/katholder/can-python-replace-javascript-in-the-future-4bbn - asm.js
http://asmjs.org/ - asm.js: Working Draft
http://asmjs.org/spec/latest/ - Manual asm.js Demonstration
https://www.youtube.com/watch?v=qkiqMuf5M84 - asm.js – frequently asked questions
http://asmjs.org/faq.html - When asm.js is faster than normal JS code, why should I write new code in JS?
https://stackoverflow.com/questions/16527195/when-asm-js-is-faster-than-normal-js-code-why-should-i-write-new-code-in-js - Faster Canvas Pixel Manipulation with Typed Arrays
https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipulation-with-typed-arrays/ - Anatomy of source maps
https://www.bugsnag.com/blog/source-maps/ - Source Map Revision 3 Proposal
https://sourcemaps.info/spec.html - Integrovaná vývojová prostředí ve Fedoře: vykreslování grafů s využitím knihoven Numpy a matplotlib
https://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-vykreslovani-grafu-s-vyuzitim-knihoven-numpy-a-matplotlib/ - Integrovaná vývojová prostředí ve Fedoře: praktické použití IPython Notebooku a knihovny Numpy (2.část)
https://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-prakticke-pouziti-ipython-notebooku-a-knihovny-numpy-2-cast/ - Integrovaná vývojová prostředí ve Fedoře: praktické použití IPython Notebooku a knihovny Numpy
https://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-prakticke-pouziti-ipython-notebooku-a-knihovny-numpy/