Srovnání programovacích jazyků Python a Wolfram Language From Wikipedia, the free encyclopedia
Tato stránka podává srovnání základních funkcí programovacích jazyků Python a Wolfram Language. Python je široce rozšířený[1] open source programovací jazyk vytvořený v roce 1991 nizozemským programátorem Guido van Rossumem. Wolfram Language (dále jen WL) je programovací jazyk, jenž je jako součást komerční aplikace Mathematica od roku 1988 vyvíjen společností Wolfram Research vedenou Stephenem Wolframem.
Python i Wolfram Language jsou multiplatformní multiparadigmatické programovací jazyky, jejichž funkčnost zahrnuje mnoho oblastí matematiky, statistiky, zpracování a vizualizace dat, numerické simulace, práce se soubory, komunikace přes síť atd. Jejich vnitřní struktura a principy, na kterých jsou založeny, jsou však dramaticky odlišné. Python je založený na objektově orientovaném přístupu a dává přednost procedurálnímu programování, zatímco základní stavební kameny WL jsou výrazy a jejich úprava pomocí vzorů, přičemž preferované je programování funkcionální. Python využívá mutabilních datových struktur a jeho moto zní: "Vše je objekt."[2]. Naproti tomu WL používá téměř výhradně struktury imutabilní a za jeho moto lze vzít: "Vše je výraz."[3] S těmito odlišnostmi souvisí i syntaxe a základní funkce obou jazyků, kvůli čemuž nelze ke každému objektu v jazyce jednom přiřadit jeho ekvivalent z jazyka druhého. Ačkoli i ve WL lze emulovat objektově orientované programování a v Pythonu lze implementovat vzory, jedná se až o druhotné konstrukty, jež nejsou plně integrovány do jazyka.
Z výše uvedených důvodů je následující srovnání spíše orientační. Je porovnávána především funkčnost obsažená v základní verzi Pythonu bez dodatečných balíků s obdobnou funkčností ve WL. Předpokládá se přitom jistá znalost Pythonu a důraz je při popisu kladen spíše na WL neboť se jedná o méně rozšířený jazyk. Některé důležité oblasti jsou z důvodu odlišných přístupů obou jazyků vynechány úplně či zmíněny jen velmi letmo. Jedná se především o objektově orientované programování v případě Pythonu a o vzory a nahrazovací pravidla v případě WL. Nad rámec tohoto článku je též srovnání možností, které Python a WL nabízejí v oblasti matematiky. Historicky byl WL určen především pro práci s matematickými výrazy, pročež je podpora této oblasti ve WL velmi široká. Jako alternativu Python nabízí mnoho knihoven jako SciPy, SymPy či NumPy.
Srovnání je tematicky rozděleno do celků a prezentováno jako tabulky o dvou sloupcích, kde snahou bylo dát pokud v co nejvíce případech související kód na řádky o stejných pořadových číslech. Pokud není výslovně uvedeno jinak jsou v následujících tabulkách použity verze Python 3.8.10[4] a Wolfram Language 13.1.0[5].
Python 3 | Wolfram Language | |
---|---|---|
Komentáře | # jednořádkový komentář
# víceřádkový...
# ...komentář
|
(* jednořádkový komentář *)
(* víceřádkový...
...komentář *)
|
Základní interakce s příkazovou řádkou | print("Vypis!") # vypsání výrazu pro uživatele
input("zadej vstup: ") # získání vstupu od uživatele
quit() # ukončení daného sezení
exit() # ukončení daného sezení
|
Print["Vypis!"] (* vypsání výrazu pro uživatele *)
Input["zadej vstup: "] (* získání vstupu od uživatele *)
Quit[] (* ukončení daného sezení; lze též jen Quit *)
Exit[] (* ukončení daného sezení; lze též jen Exit *)
|
Poslední výsledek | 1 + 3 # vrátí: 4
_ # vrátí: 4
"ret" # vrátí: "ret"
_ # vrátí: "ret"
Poslední výsledek v interaktivním módu je ukládán v proměnné značené podtržítkem |
1 + 3 (* vrátí: 4 *)
% (* vrátí: 4 *)
"ret" (* vrátí: "ret" *)
% (* vrátí: "ret" *)
%% (* vrátí: 4 *)
Poslední výsledek je ukládán v proměnné značené procentem |
Nápověda a definice | type(a) # datový typ objektu a
help(a) # získání nápovědy pro objekt a
globals() # slovník globálních proměnných
locals() # slovník lokálních proměnných
vars(a) # slovník atributů objektu a
dir(a) # seznam atributů třídy objektu a
V prostředí příkazové řádky IPython lze nápovědu vyvolat podobně jako ve WL vypsáním jednoho |
Head[a] (* hlavička výrazu a *)
?a (* nápověda pro symbol a; lze též Information[a] *)
Names["Global`*"] (* seznam všech globálních proměnných *)
Names["cont`*"] (* seznam všech proměnných v kontextu cont *)
Definition[a] (* vypiš definici symbolu a *)
Na rozdíl do Pythonu nemají ve WL objekty klasické typy, ale každý výraz má hlavičku, která určuje jeho „typ“. Hlavičku daného výrazu lze zjistit funkcí |
Smazání objektu | del a # smaž objekt a
Výše uvedený kód lze psát i jako volání funkce |
Clear[a] (* smaž hodnotu symbolu a *)
ClearAll[a] (* smaž hodnoty symbolu a včetně metadat *)
Remove[a] (* vyjmi symbol a ze jmenného prostoru *)
a =. (* smaž hodnotu symbolu a *)
Funkcí |
Vyhodnocení kódu | eval("1 + 2*3") # vyhodnoť výraz vypsaný v řetězci
exec("a = 1") # proveď kód vypsaný v řetězci
compile("a = 1", "<string>", "exec") # zkompiluj zadaný kód
Funkce |
ToExpression["1 + 2*3"] (* převeď výraz vypsaný v řetězci na kód... *)
ToExpression["a = 1"] (* ...bez ohledu na to, zda jde o výraz či blok kódu *)
f = Compile[{{x, _Real}}, x + 1] (* zkompiluj výraz do nízkoúrovňové reprezentace *)
f[1.] (* vrátí: 2. *)
Ve WL lze s kódem nakládat jako s daty a tak obyčejně není třeba kód vyjadřovat jako řetězec, který je poté nutno převést na kód. Pokud to potřeba je, lze použít funkci |
Provádění kódu ve skriptu | V prostředí systémové příkazové řádky (zde pro konkrétnost Bash):
$ python3 skript.py # provedení skriptu
$ python3 -m modul # provedení modulu jako skriptu
Provedení modulu jako skriptu lze provést pomocí parametru |
V prostředí systémové příkazové řádky (zde pro konkrétnost Bash):
$ wolframscript -f balik.wls # aktualizuje $ScriptCommandLine
$ WolframKernel -script balik.wls # nechá $ScriptCommandLine prázdnou
Skript lze provést buď přímo voláním výpočetního jádra WL příkazem |
Načítání balíčků | import numpy # načtení balíku numpy
import numpy as np # načtení balíku a nastavení zkratky
from numpy import * # načtení všech funkcí/proměnných z balíku
from numpy import array # načtení konkrétní funkce
Základní ucelenou jednotkou kódu jsou moduly, které lze importovat příkazem |
Needs["Developer`"] (* načtení balíku Developer *)
Needs["Developer`"->"dev`"] (* načtení balíku a nastavení aliasu *)
<<balik.wl (* vyhodnocení balíku; též Get["balik.wl"] *)
PacletInstall["paclet"] (* instalace pacletu *)
Základní ucelenou jednotkou kódu jsou balíky, jež lze importovat funkcí |
Porovnání hodnot | a = [1, 2, 3] # definuj objekt a
b = [1, 2, 3] # definuj objekt b stejné hodnoty
c = a # do proměnné c vlož odkaz na objekt odkazovaný proměnnou a
a == b # vrátí: True; oba objekty mají stejnou hodnotu
a is b # vrátí: False; tyto objekty ale odkazují na dvě místa v paměti
a is c # vrátí: True; naproti tomu a i c odkazují na stejné místo
b is not c # vrátí: True
V Pythonu jsou proměnné v podstatě odkazy na kusy paměti, ve kterých jsou uloženy odkazované objekty. Dvě proměnné mohou odkazovat na dva objekty, jejichž tvar je totožný, jsou nicméně uloženy na dvou různých místech paměti. Pro takové proměnné vrátí porovnání pomocí operátoru |
a = {1, 2, 3} (* definuj výraz a *)
b = {1, 2, 3} (* definuj výraz b stejné hodnoty *)
a == b (* vrátí: True; oba výrazy mají stejnou hodnotu *)
a === b (* vrátí: True; tyto výrazy mají i stejný tvar *)
0 == 0.0 (* vrátí: True; hodnota výrazu je stejná *)
0 === 0.0 (* vrátí: False; tyto výrazy ale nejsou totožné *)
0 =!= 0.0 (* vrátí: True *)
Ve WL jsou výrazy imutabilní struktury, jejichž identita se odvíjí čistě od jejich tvaru. V kódu výše jsou do proměnných |
Číselná reprezentace objektů | hash(a) # hash objektu a
id(a) # jedinečné číslo identifikující objekt a
Dva objekty mohou mít tutéž hashovou hodnotu. Číslo |
Hash[a] (* hash výrazu a *)
CreateUUID[a] (* náhodně vytvořené UUID číslo výrazu a *)
Dva výrazy mohou mít tutéž hashovou hodnotu. Pro daný výraz lze ve WL vygenerovat jednoznačné UUID číslo funkcí |
Python 3 | Wolfram Language | |
---|---|---|
Řetězce | "ret" # vrátí: 'ret'
'ret' # vrátí: 'ret'
r"ret\\ezec" # vrátí: 'ret\\\\ezec'
"""ret 'ezec' """ # vrátí: "ret 'ezec' "
'''ret "ezec" ''' # vrátí: 'ret "ezec" '
'ret' + 'ezec' # vrátí: 'retezec'
'ret' 'ezec' # vrátí: 'retezec'
3 * 'ret' # vrátí: 'retretret'
len('retezec') # počet znaků; vrátí: 7
Řetězce jsou typu |
"ret" (* vrátí: "ret" *)
"ret 'ezec' " (* vrátí: "ret 'ezec' " *)
"ret \"ezec\" " (* vrátí: "ret "ezec" " *)
"ret" <> "ezec" (* vrátí: "retezec" *)
StringJoin["ret","ezec"] (* vrátí: "retezec" *)
StringRepeat["ret",3] (* vrátí: "retretret" *)
StringLength["retezec"] (* vrátí: 7 *)
Řetězce mají hlavičku |
Indexování řetězců | "retezec"[2] # vrátí: 't'
"retezec"[-3] # vrátí: 'z'
"retezec"[2:-3] # vrátí: 'te'
for c in "retezec": print(c) # cyklus přes jednotlivé znaky
Indexování začíná od nuly. Při indexování od konce se začíná od . U rozsahů není poslední index součástí rozsahu. |
StringPart["retezec",3] (* vrátí: "t" *)
StringPart["retezec",-3] (* vrátí: "z" *)
StringTake["retezec",{3,-4}] (* vrátí: "te" *)
Do[Print[c], {c, Characters["retezec"]}] (* cyklus přes znaky *)
Indexování začíná od jedničky. Při indexování od konce se začíná od . U rozsahů je poslední index součástí rozsahu. |
Formátované řetězce | chl, jab = 3, 6
# všechny následující řádky vrátí: 'kup 3 chleby a 6 jablek'
f"kup {chl} chleby a {jab} jablek"
"kup {} chleby a {} jablek".format(chl, jab)
"kup {1} chleby a {0} jablek".format(jab, chl)
"kup {x} chleby a {y} jablek".format(x=chl,y=jab)
Pokročilešjí možnosti umožňuje třída |
{chl, jab} = {3, 6};
(* všechny následující řádky vrátí: "kup 3 chleby a 6 jablek" *)
StringForm["kup `` chleby a `` jablek", chl, jab]
StringForm["kup `2` chleby a `1` jablek", jab, chl]
StringTemplate["kup `x` chleby a `y` jablek"][<|"x"->chl,"y"->jab|>]
|
Unicode znaky | "\756" # osmičková soustava; vrátí: 'Ǯ'
"\xf9" # dvě šestnáctkové číslice; vrátí: 'ù'
"\u51a3" # čtyři šestnáctkové číslice; vrátí: '冣'
"\U000051a3" # osm šestnáctkových číslic; vrátí: '冣'
"\N{CYRILLIC CAPITAL LETTER ZHE}" # vrátí: 'Ж'
Python umožňuje vkládat Unicode znaky v různých formátech, včetně jejich Unicode jména, viz poslední řádek výše. Ačkoli 32bitová verze uvozená znaky |
"\756" (* vrátí: "Ǯ" *)
"\.f9" (* vrátí: "ù" *)
"\:51a3" (* vrátí: "冣" *)
"\|0051a3" (* vrátí: "冣" *)
"\[WLjmeno]" (* Zápis pomocí jména ve WL *)
Ne každý Unicode znak má své WL jméno, přičemž WL jméno se může u těch znaků, které ho mají, lišit od jejich Unicode jména. Tak například znak → má kódový bod U+2192, Unicode jméno "Rightwards Arrow"[11], přičemž jeho WL jméno zní "RightArrow"[12]. |
Převod mezi řetězci a čísly | str(42) # vrátí: '42'
ascii('znak Ӓ') # vrátí: "'znak \\u04d2'"
chr(1234) # vrátí: 'Ӓ'
ord('Ӓ') # vrátí: 1234
|
ToString[42] (* vrátí: "42" *)
ToString["znak Ӓ",CharacterEncoding->"ASCII"] (* vrátí: "znak \:04d2" *)
FromCharacterCode[1234] (* vrátí: Ӓ *)
ToCharacterCode["Ӓ"] (* vrátí: {1234} *)
Výše uvedený kód nelze brát jako plnohodnotné srovnání s Pythonovským kódem v levém sloupci, protože jednotlivé funkce nejsou v daných jazycích ekvivalentní. Viz např. funkci |
Řetězcová reprezentace | ### uživatelem definovaná reprezentace
class tridaR: # vytvoř třídu tridaR
s = 42
# definování reprezentace pro repr
def __repr__(self):
return "stav {}".format(self.s)
# definování reprezentace pro str
def __str__(self):
return "vypis {}".format(self.s)
x = tridaR() # vytvoř objekt x třídy tridaR
str(x) # vrátí: 'vypis 42'
print(x) # vypíše: 'vypis 42'
repr(x) # vrátí: 'stav 42'
x # vypíše: 'stav 42'
|
(* --- uživatelem definový formát výrazů --- *)
(* definuj výchozí reprezentaci výrazu tridaR *)
Format[tridaR[s_]] := "stav "<>ToString[s]
x = tridaR[42]; (* vytvoř proměnnou x s hlavičkou tridaR *)
StandardForm[x] (* vypíše: "stav 42" *)
Print[x] (* vypíše: "stav 42" *)
InputForm[x] (* vypíše: tridaR[42] *)
x (* vypíše: "stav 42" *)
Opět, kód v levém a pravém sloupci není zcela ekvivalentní. WL umožňuje tentýž výraz vypsat či vykreslit v několika různých reprezentacích. Nízkoúrovňovou reprezentací je |
Regulární výrazy | import re # regulární výrazy
re.findall('\\w\\d', 'a b1 c d2') # vrátí: ['b1', 'd2']
Podporu regulárních výrazů lze dostat voláním modulu |
(* oba následující řádky vrátí: {"b1", "d2"} *)
StringCases["a b1 c d2", RegularExpression["\\w\\d"]]
StringCases["a b1 c d2", WordCharacter~~DigitCharacter]
Regulární výrazy lze vkládat buď pomocí výrazu |
Python 3 | Wolfram Language | |
---|---|---|
Základní číselné typy | 3 # typ int
3.0 # typ float
3.e5 # vědecká notace
3 + 2j # komplexní číslo, typ complex
float(3) # převod int na float
int(3.1) # převod float na int
float("23.1") # převod řetězce na float
int("23") # převod řetězce na int
Základní číselné typy jsou |
3 (* typ Integer *)
3.0 (* typ Real *)
3.*^5 (* vědecká notace *)
3 + 2 I (* komplexní číslo, typ Complex *)
3 / 2 (* racionální číslo, typ Rational *)
N[3] (* převod Integer na Real *)
Floor[3.1] (* převod Real na Integer, lze použít i Round[3.1] *)
ToExpression["23"] (* převod řetězce na Integer *)
ToExpression["23.1"] (* převod řetězce na Real *)
Základní číselné typy jsou |
Číselné soustavy | 10 # desetinná soustava
0b1010 # dvojková soustava
0o12 # osmičková soustava
0xa # šestnáctková soustava
bin(10) # převod do dvojkové soustavy
oct(10) # převod do osmičkové soustavy
hex(10) # převod do šestnáctkové soustavy
Výše vyjádřeno číslo 10 v různých číselných soustavách. |
10 (* desetinná soustava *)
2^^1010 (* dvojková soustava *)
8^^12 (* osmičková soustava *)
16^^a (* šestnáctková soustava *)
IntegerString[10, 2] (* převod do dvojkové soustavy *)
IntegerString[10, 8] (* převod do osmičkové soustavy *)
IntegerString[10, 16] (* převod do šestnáctkové soustavy *)
Lze použít i |
Aritmetika | 1 + 3 # vrátí: 4
1 - 3 # vrátí: -2
2 / 3 # vrátí: 0.6666666
2. / 3. # vrátí: 0.6666666
2 * 3 # vrátí: 6
Dělení celých i reálných čísel vrátí reálné číslo, tj. typ |
1 + 3 (* vrátí: 4 *)
1 - 3 (* vrátí: -2 *)
2 / 3 (* vrátí: 2/3 *)
2. / 3. (* vrátí: 0.666667 *)
2 * 3 (* vrátí: 6 *)
2 3 (* vrátí: 6 *)
Dělení celých čísel vrátí racionální číslo, tj. typ |
Mocniny | 3 ** 2 # vrátí: 9
pow(3, 2) # vrátí: 9
|
3 ^ 2 (* vrátí: 9 *)
Power[3, 2] (* vrátí: 9 *)
|
Celočíselné dělení a zbytek | 5 // 2 # vrátí: 2
5.0 // 2.0 # vrátí: 2.0
5 % 2 # vrátí: 1
5.0 % 2.0 # vrátí: 1.0
divmod(5, 2) # vrátí: (2, 1)
|
Quotient[5, 2] (* vrátí: 2 *)
Quotient[5.0, 2.0] (* vrátí: 2, to jest celé číslo *)
Mod[5, 2] (* vrátí: 1 *)
Mod[5.0, 2.0] (* vrátí: 1.0 *)
QuotientRemainder[5, 2] (* vrátí: {2, 1} *)
Funkce |
Porovnávání | 3 == 2 # vrátí: False
2 != 3 # vrátí: True
2 < 3 # vrátí: True
3 <= 3 # vrátí: True
4 > 3 # vrátí: True
3 >= 3 # vrátí: True
3.0 == 3 # vrátí: True
2 < 3 < 4 # vrátí: True
Složené podmínky jsou možné, viz poslední řádek. |
3 == 2 (* vrátí: False *)
2 != 3 (* vrátí: True *)
2 < 3 (* vrátí: True *)
3 <= 3 (* vrátí: True *)
4 > 3 (* vrátí: True *)
3 >= 3 (* vrátí: True *)
3.0 == 3 (* vrátí: True *)
2 < 3 < 4 (* vrátí: True *)
Složené podmínky jsou možné, viz poslední řádek. |
Základní matematika | abs(-2) # absolutní hodnota; vrátí: 2
round(2.8) # zaokrouhlování; vrátí: 3
min(3, 8, -1) # minimum; vrátí: -1
max(3, 8, -1) # maximum; vrátí: 8
max([3, 8, -1]) # funguje i na seznamy; vrátí: 8
sum([3, 8, -1]) # součet seznamu; vrátí: 10
sum(i**2 for i in range(4)) # součet vygenerovaných hodnot; vrátí: 14
Poslední výraz je roven součtu druhých mocnin . Využito je generátoru, který bere hodnoty ze seznamu |
Abs[-2] (* vrátí: 2 *)
Round[2.8] (* vrátí: 3 *)
Min[3, 8, -1] (* vrátí: -1 *)
Max[3, 8, -1] (* vrátí: 8 *)
Max[{3, 8, -1}] (* vrátí: 8 *)
Total[{3, 8, -1}] (* vrátí: 10 *)
Sum[i^2, {i, 3}] (* vrátí: 14 *)
Funkce |
Python 3 | Wolfram Language | |
---|---|---|
Logické operace | True # pravda
False # nepravda
x and y # konjunkce
x or y # disjunkce
not x # negace
"" and "neco" # vrátí: ''
"" or "neco" # vrátí: 'neco'
all([True, True, False]) # vrátí: False
any([True, True, False]) # vrátí: True
Hodnoty |
True (* pravda *)
False (* nepravda *)
x && y (* konjunkce, též And[x, y] *)
x || y (* disjunkce, též Or[x, y] *)
!x (* negace, též Not[x] *)
And[True, True, False] (* vrátí: False *)
Or[True, True, False] (* vrátí: True *)
TrueQ[x] (* vrátí False, pokud x není explicitně True *)
Boole[True] (* vrátí: 1 *)
Boole[False] (* vrátí: 0 *)
Operátory |
Bitové operace | x & y # bitový součin
x | y # bitový součet
x ^ y # bitová nonekvivalence
~x # bitová negace
x << n # bitový posuv doleva
x >> n # bitový posuv doprava
Python podporuje i přiřazovací verze bitových operátorů: |
BitAnd[x, y] (* bitový součin *)
BitOr[x, y] (* bitový součet *)
BitXor[x, y] (* bitová nonekvivalence *)
BitNot[x] (* bitová negace *)
BitShiftLeft[x, n] (* bitový posuv doleva *)
BitShiftRight[x, n] (* bitový posuv doprava *)
Bitové operátory nemají ve WL žádné vyjádření pomocí znaků ve stylu Pythonu[19]. |
Podmínky | if x > 0: # podmíněný příkaz
print(x) # vyhodnoť tento kód, je-li podmínka pravdivá
else:
x = 0 # jinak vyhodnoť tento kód
if x > 5: # zřetězený podmíněný příkaz
x = 1
elif x > 0: # příkaz může mít tolik elif kolik chce
print(x)
else:
x = 0
|
If[x > 0, (* podmíněný příkaz *)
Print[x], (* vyhodnoť tento kód, je-li podmínka pravdivá *)
x = 0 (* jinak vyhodnoť tento kód *)
]
Which[ (* výraz Which *)
x > 5, x = 1, (* podmínky na lichých pozicích... *)
x > 0, Print[x], (* ...kód na sudých *)
True, x = 0 (* jako poslední podmínku lze vzít True *)
]
(* čtvrtý argument je vyhodnocen, nelze-li určit pravdivost podmínky v prvním argumentu *)
If[x > 0,
Print[x],
x = 0,
Print["x nema hodnotu"]
]
Ve WL je podmíněný příkaz vyjádřen výrazem a to výrazem s hlavičkou |
Porovnání se vzorem | x = 'ret' # vstupní proměnná
match x: # porovnej proměnnou s jednotlivými případy
case 'ret':
print('x vyhovuje prvnimu pripadu')
case 'ezec':
print('x vyhovuje druhemu pripadu')
case _:
print('zadna jina hodnota nepasuje')
Od verze 3.10 podporuje Python prostřednictvím příkazu match[20][21] též porovnání výrazu se vzorem, anglicky pattern matching. V příkladu výše vypíše kód |
x = "ret";
Switch[x,
"ret", Print["x vyhovuje prvnimu pripadu"],
"ezec", Print["x vyhovuje druhemu pripadu"],
_, Print["zadna jina hodnota nepasuje"]
]
Porovnávání se vzorem je jedním ze stavebních kamenů WL a je tak silně integrován do jazyka. Mimo jiné ho lze uplatnit ve výrazu |
Python 3 | Wolfram Language | |
---|---|---|
Datové struktury | [1, 2, 3, 4] # list
(1, 2, 3, 4) # tuple
{1, 2, 3, 4} # set
frozenset({1, 2, 3, 4}) # frozenset
{'a':3, 'b':4, 'c':5} # dict
bytes([1, 2, 3]) # bytes; vrátí: b'\x01\x02\x03'
bytearray([1, 2, 3]) # bytearray; vrátí: bytearray(b'\x01\x02\x03')
Python nabízí několik vestavěných datových struktur: list (pole, mutabilní), dict (asociativní pole, mutabilní), tuple (uspořádaná n-tice, imutabilní), set (množina, to jest každý prvek nejvíc jednou, mutabilní), frozenset („zmražená“ množina, imutabilní), bytearray (pole bytů, mutabilní), bytes (pole bytů, imutabilní). Dále je k dispozici množství dalších struktur v modulu |
{1, 2, 3, 4} (* List *)
<|"a"->3, "b"->4, "c"->5|> (* Association *)
ByteArray[{1, 2, 3}] (* ByteArray["AQID"] *)
WL má dvě základní datové struktury a to |
Počet prvků | len([1, 2, 3, 4]) # vrátí: 4
len({'a':3, 'b':4, 'c':5}) # vrátí: 3
|
Length[{1, 2, 3, 4}] (* vrátí: 4 *)
Length[<|"a"->3, "b"->4, "c"->5|>] (* vrátí: 3 *)
|
Příslušnost prvku | "a" in [3, "b", "a", 4] # vrátí: True
|
MemberQ[{3, "b", "a", 4}, "a"] (* vrátí: True *)
|
Pole | [1, "a", [2, 3], 4] # seznam může obsahovat různé objekty
[[1, 2], [2, 3]] # vnořené seznamy
["a", "b", "c"] + ["u", "v"] # vrátí: ['a', 'b', 'c', 'u', 'v']
s = ["a", "b", "c", "d"]
s[0] # vrátí: 'a'
s[-2] # vrátí: 'c'
s[1:3] # vrátí: ['b', 'c']
s[0:-1:2] # vrátí: ['a', 'c']
s[1] = "e" # s je nyní tvaru ['a', 'e', 'c', 'd']
s[1:3] = ["f", "g"] # s je nyní tvaru ['a', 'f', 'g', 'd']
del s[2] # s je nyní tvaru ['a', 'f', 'd']
V Pythonu se pole nazývají seznamy, anglicky lists, jejichž prvky se vypisují do hranatých závorek. Pole jsou mutabilní struktury, jež mohou obsahovat objekty různého druhu. Indexace se provádí hranatými závorkami, začíná nulou a lze indexovat i odzadu pomocí záporných čísel. Části seznamu lze obdržet vložením rozsahu čísel ve tvaru |
{1, "a", {2, 3}, 4} (* seznam může obsahovat různé objekty *)
{{1, 2}, {2, 3}} (* vnořené seznamy *)
{"a", "b", "c"}~Join~{"u", "v"} (* vrátí: {"a", "b", "c", "u", "v"} *)
s = {"a", "b", "c", "d"}
s[[1]] (* vrátí: "a" *)
s[[-2]] (* vrátí: "c" *)
s[[2;;3]] (* vrátí: {"b", "c"} *)
s[[1;;-1;;2]] (* vrátí: {"a", "c"} *)
s[[2]] = "e" (* s je nyní tvaru {"a", "e", "c", "d"} *)
s[[2;;3]] = {"f", "g"} (* s je nyní tvaru {"a", "f", "g", "d"} *)
Drop[s, {3}] (* vrátí: {"a", "f", "d"} *)
Ve WL se pole též nazývají seznamy, jejichž prvky se zapisují do složených závorek. Pole jsou imutabilní struktury, jež mohou obsahovat jako prvky různé výrazy. Indexace se provádí dvojitými hranatými závorkami, začíná jedničkou[pozn. 2] a lze indexovat i odzadu pomocí záporných čísel. Části seznamu lze obdržet vložením rozsahu čísel ve tvaru |
Asociativní pole | ap = {"a": 2, 5: max, print: [3, 42]} # klíče i hodnoty mohou být různého typu
list(ap.keys()) # vrátí: ['a', 5, <built-in function print>]
list(ap.values()) # vrátí: [2, <built-in function max>, [3, 42]]
ap["a"] # vrátí: 2
Asociativní pole se v Pythonu nazývají slovníky, anglicky dictionaries, jež lze vytvořit voláním konstruktoru |
ap = <|"a"->2, 5->Sin, Print->{3, 42}|> (* klíče i hodnoty mohou být různého typu *)
Keys[ap] (* {a, 5, Print} *)
Values[ap] (* {2, Sin, {3, 42}} *)
ap["a"] (* 2 *)
ap[[3]] (* {3, 42} *)
ap[[Key[5]]] (* Sin *)
Ve WL se asociativní pole nazývají asociace, anglicky associations, a odpovídají výrazům s hlavičkou |
Následující srovnání není zcela ekvivalentní, protože WL upřednostňuje funkcionální přístup. Ačkoli tedy WL obsahuje například for cykly, je snaha se těmto vyhýbat a místo nich používat mapování funkcí pomocí funkce Map
či jí příbuzných funkcí. Pro tvorbu polí je též místo for cyklů často využíváno funkcí Table
a Array
. Dále je třeba mít na paměti, že WL indexuje od jedničky a nabízí zkrácenou syntaxi pro případy, kdy sčítací indexy skutečně od jedničky začínají. V rámci zachování konzistence mezi Pythonským a WL kódem ale v následujícím vynucujeme indexování od nuly.
Python 3 | Wolfram Language | |
---|---|---|
For cyklus | for i in range(3): # for cyklus
print("index je: ", i)
for i in range(100): # for cyklus
if i < 5: continue # přeskoč jednu iteraci
print("index je: ", i)
if i > 10: break # ukonči předčasně cyklus
Iterátor |
For[i = 0, i < 3, i++, Print["Index je: ", i]] (* for cyklus *)
Do[Print["Index je: ", i], {i, 0, 2}] (* alternativní tvar *)
Do[
If[i < 5, Continue[]]; (* přeskoč jednu iteraci *)
Print["Index je: ", i];
If[i > 10, Break[]]; (* ukonči předčasně cyklus *)
, {i, 100}]
Funkce |
While cyklus | i = 0;
while i < 3: # while cyklus
print("index je: ", i)
i = i + 1
|
i = 0;
While[i < 3, Print["Index je: ", i++]] (* while cyklus *)
i = 0;
Until[i >= 3, Print["Index je: ", i++]] (* repeat-until cyklus *)
Od verze 13.1 podporuje WL i repeat-until cyklus funkcí |
Komprehenze | [i**2 for i in range(4)] # vrátí: [0, 1, 4, 9]
{i: i**2 for i in range(4)} # vrátí: {0: 0, 1: 1, 2: 4, 3: 9}
{i**2 for i in range(4)} # vrátí: {0, 1, 4, 9}
|
Table[i^2, {i, 0, 3}] (* vrátí: {0, 1, 4, 9} *)
Association[Table[i->i^2, {i, 0, 3}]] (* vrátí: <|0->0, 1->1, 2->4, 3->9|> *)
AssociationMap[#^2&, Range[0, 3]] (* vrátí: <|0->0, 1->1, 2->4, 3->9|> *)
Namísto komprehenzí lze použít buď mapování pomocí funkcí |
Iterace přes prvky pole | # for cyklus přes prvky
for i in ['a', 'b', 'c']:
print("prvek je: ", i)
# prvky spolu s indexy
for i, p in enumerate(['a', 'b', 'c']):
print("index je: ", i, " prvek je: ", p)
# for cyklus přes seřazené pole
for i in sorted([3, 1, 2]):
print("prvek je: ", i)
# for cyklus odzadu
for i in reversed([1, 2, 3]):
print("prvek je: ", i)
Python používá iterátory, jež lze pro danou datovou strukturu získat funkcí |
(* for cyklus přes prvky *)
Do[Print["prvek je: ", i], {i, {"a", "b", "c"}}] (* P *)
Print["prvek je: ", #]& /@ {"a", "b", "c"} (* F *)
(* prvky spolu s indexy *)
s = {"a", "b", "c"};
Do[Print["index je: ", i," prvek je: ", s[[i]]], {i, Range[Length[s]]}] (* P *)
MapIndexed[Print["index je: ", #2, " prvek je: ", #1]&, {"a", "b", "c"}] (* F *)
(* for cyklus přes seřazené pole *)
Do[Print["prvek je: ", i], {i, Sort@{3, 1, 2}}] (* P *)
Print["prvek je: ", #]& /@ Sort[{"a", "b", "c"}] (* F *)
(* for cyklus odzadu *)
Do[Print["prvek je: ", i], {i, Reverse@{1, 2, 3}}] (* P *)
Print["prvek je: ", #]& /@ Reverse[{"a", "b", "c"}] (* F *)
WL nepoužívá iterátory známé z Pythonu. Výše jsou pro každý typ for cyklu uvedeny dvě různé varianty: P v komentáři označuje procedurální variantu a F označuje variantu funkcionální. Zápisy výše přitom nejsou zcela ekvivalentní Pythonskému kódu. Například funkce |
Iterace přes prvky asociativního pole | # for cyklus přes klíče slovníku
for i in {'a':3, 'b':4, 'c':5}:
print("klic je: ", i)
# for cyklus přes hodnoty slovníku
for i in {'a':3, 'b':4, 'c':5}.values():
print("hodnota je: ", i)
# for cyklus přes hodnoty slovníku
for k, h in {'a':3, 'b':4, 'c':5}.items():
print("par je: ", k, h)
|
(* for cyklus přes klíče *)
Do[Print["klic je: ", i], {i, Keys[<|"a"->3, "b"->4, "c"->5|>]}] (* P *)
Print["klic je: ", #]& /@ Keys[<|"a"->3, "b"->4, "c"->5|>] (* F *)
(* for cyklus přes hodnoty *)
Do[Print["hodnota je: ", i], {i, <|"a"->3, "b"->4, "c"->5|>}] (* P *)
Print["hodnota je: ", #]& /@ <|"a"->3, "b"->4, "c"->5|> (* F *)
(* for cyklus přes páry *)
Do[Print["par je: ", kh], {kh, List@@@Normal[<|"a"->3, "b"->4, "c"->5|>]}] (* P *)
KeyValueMap[Print["par je: ", #1, #2]&, <|"a"->3, "b"->4, "c"->5|>] (* F *)
Výše jsou pro každý typ for cyklu uvedeny dvě různé varianty: P v komentáři označuje procedurální variantu a F označuje variantu funkcionální. Zápisy výše přitom nejsou zcela ekvivalentní Pythonskému kódu. Například funkce |
Iterace přes několik polí | # for cyklus přes dvojice
for i, j in zip(['a', 'b', 'c'], ['d', 'e', 'f']):
print("dvojice je: ", i, j)
|
(* for cyklus přes dvojice... *)
Do[Print["dvojice je: ", i], {i, Thread[{{"a", "b", "c"}, {"d", "e", "f"}}]}]
(* ...a jeho funkcionální alternativa *)
MapThread[Print["dvojice je: ", ##]&, {{"a", "b", "c"}, {"d", "e", "f"}}]
Místo |
Mapování | list(map(lambda x: x + 1, [3, 5, -1])) # vrátí: [4, 6, 0]
list(map(lambda x, y: x + y, [3, 5, -1], [2, -2, 7])) # vrátí: [5, 3, 6]
Funkce |
Map[(# + 1)&, {3, 5, -1}] (* vrátí: {4, 6, 0} *)
(# + 1)& /@ {3, 5, -1} (* vrátí: {4, 6, 0} *)
MapThread[Plus, {{3, 5, -1}, {2, -2, 7}}] (* vrátí: {5, 3, 6} *)
Mapovat lze i funkce definované obvyklým způsobem, viz třetí řádek. Funkce |
Výběr prvků pole dle kritéria | list(filter(lambda x: x > 0, [3, 5, -1])) # vrátí: [3, 5]
Funkce |
Select[{3, 5, -1}, (# > 0)&] (* vrátí: {3, 5} *)
Použít lze i funkce definované obvyklým způsobem. Ve WL existuje i funkce |
Výběr prvků pole dle rozmezí | pole = ["a", "b", "c", "d", "e", "f", "g"]
roz = slice(1, 4)
pole[roz] # vrátí: ['b', 'c', 'd']
Konstruktor |
pole = {"a", "b", "c", "d", "e", "f", "g"}
roz = Span[2, 4] (* lze též: roz = 2 ;; 4 *)
pole[[roz]] (* vrátí: {"b", "c", "d"} *)
Výraz |
Python 3 | Wolfram Language | |
---|---|---|
Volání a přiřazení | f(3) # volání pomocí kulatých závorek
g = f # funkci f přiřadíme do proměnné g
g(3) # volání g(3) vrátí totéž co f(3)
Volání funkce se v Pythonu provádí vypsáním jména funkce, za nímž jsou v kulatých závorkách vypsány argumenty. Funkce jsou first-class objekty, takže se chovají jako jiné objekty a lze je přiřazovat do proměnných podobně jako čísla či řetězce. |
f[3] (* volání pomocí hranatých závorek *)
g = f (* funkci f přiřadíme do proměnné g *)
g[3] (* volání g[3] vrátí totéž co f[3] *)
Podobně jako v Pythonu jsou i ve WL funkce first-class objekty. Při jejich volání se ale používají hranaté závorky. |
Definice funkce | def fun(arg): # definice je uvozena slovem def
x = arg + 1 # lokální proměnné
return x # návratová hodnota
fun(3) # vrátí: 4
Definice se uvozuje klíčovým slovem |
fun[arg_] := Module[{x}, (* definice má tvar přiřazení *)
x = arg + 1; (* proměnné lze lokalizovat např. pomocí Module *)
Return[x] (* místo Return[x] stačí psát pouze x *)
]
fun[3] (* vrátí: 4 *)
Definice má tvar (obyčejně odloženého) přiřazení, kde na levé straně je jméno definované funkce, za níž následuje v hranatých závorkách vzor obsahující vstupní parametry, a na straně pravé je tělo funkce. Pro lokalizaci proměnných lze použít několik blokových struktur jako |
Výchozí hodnoty parametrů | def fun(arg=42):
x = arg + 1
return x
fun() # vrátí: 43
|
fun[arg_: 42] := Module[{x},
x = arg + 1;
Return[x]
]
fun[] (* vrátí: 43 *)
|
Pojmenované parametry | def fun(arg1, arg2):
return arg1 + arg2
fun(1, 2) # vrátí: 3
fun(arg2=2, arg1=1) # vrátí: 3
fun(1, arg2=2) # vrátí: 3
|
(* definuj volby s výchozími hodnotami *)
Options[fun] = {"arg1"->0, "arg2"->10};
fun[OptionsPattern[]] := OptionValue["arg1"] + OptionValue["arg2"]
fun["arg1"->1, "arg2"->2] (* vrátí: 3 *)
fun["arg2"->1, "arg1"->2] (* vrátí: 3 *)
fun["arg1"->2] (* vrátí: 12 *)
Obdobnou funkci, jakou v Pythonu hrají pojmenované parametry, hrají ve WL volby (anglicky options), jež jsou definovány odlišným způsobem od pozičních argumentů. Ve WL je daný parametr buď poziční anebo „pojmenovaný“, nemůže být obojím. Na rozdíl od pozičních argumentů mohou být volby uvedeny v jakémkoliv pořadí anebo nemusejí být uvedeny vůbec, v kterémžto případě se použijí jejich výchozí hodnoty. |
Libovolný počet argumentů | def f(*args): # předem neurčený počet pozičních parametrů
print(args)
f(1) # vypíše: (1,)
f(1,2) # vypíše: (1, 2)
f(1,"ret",2) # vypíše: (1, 'ret', 2)
Předem neurčený počet pozičních parametrů lze v definici funkce značit hvězdičkou předcházející identifikátor argumentů. Pro pojmenované parametry se použijí hvězdičky dvě. |
f[args__] := Print[args] (* předem neurčený počet pozičních parametrů *)
f[1] (* vypíše: 1 *)
f[1, 2] (* vypíše: 12 *)
f[1, "ret", 2] (* vypíše: 1ret2 *)
Předem neurčený počet pozičních parametrů lze v definici funkce značit dvěma či třemi podtržítky za identifikátorem argumentů. Dvě podtržítka označují jeden a více argumentů, tři podtržítka označují nula a více argumentů. |
Dokumentační řetězce | def f(arg):
'''Moje funkce''' # dokumentační řetězec
return arg
help(f) # vyvolání nápovědy, kde je popisek viditelný
Krátký popis funkce lze vložit do dokumentačního řetězce následující úvodní řádek definice. Tento popis je přístupný v nápovědě k funkci a je uložen jako atribut |
f::usage = "Moje funkce"; (* dokumentační řetězec *)
f[arg_] := arg
?f (* vyvolání krátké nápovědy s viditelným popiskem *)
Krátký popis funkce |
Typ parametrů | def f(a: str)->str: # anotace pro vstupní a výstupní hodnoty
return a + " ale prece"
f("pozde") # vrátí: 'pozde ale prece'
f(2) # vyvolá výjimku TypeError, protože nelze sčítat čísla s řetězci
V Pythonu nelze přímo určit datový typ přijímaných argumentů. Blízko se v tomto ohledu pohybují anotace, ty ale mají pouze popisný charakter. |
f[a_String] := a <> " ale prece" (* vstupní argument typu String *)
f["pozde"] (* vrátí: "pozde ale prece" *)
f[2] (* vrátí: f[2], to jest zůstane nevyhodnoceno *)
Ve WL lze specifikovat typ přijímaných argumentů. Pokud definice funkce nevyhovuje dodaným hodnotám argumentů, zůstane funkce nevyhodnocena. |
Anonymní funkce | f = lambda x: x + 1 # lambda funkce, jež přičte jedničku
f(2) # vrátí: 3
g = lambda x, y, z: [x + y, x + z] # více parametrů
g(7, 1, 2) # vrátí: [8, 9]
V Pythonu se anonymní funkce nazývají lambda funkce a uvozují se klíčovým slovem |
f = (# + 1) & (* ryzí funkce, jež přičte jedničku *)
f[2] (* vrátí: 3 *)
g = {#1 + #2, #1 + #3} & (* více proměnných *)
g[7, 1, 2] (* vrátí: {8, 9} *)
g = (#1 + {##2}) & (* alternativní zápis *)
Ve WL se anonymní funkce nazývají ryzí funkce (anglicky pure functions) a odpovídají výrazům s hlavičkou |
Python 3 | Wolfram Language | |
---|---|---|
Příkaz assert | assert x == "ret" # pokud x != "ret", tak vyvolá výjimku
assert x == "ret", "neni ret" # chybová hláška je nastavena na "neni ret"
Příkazy |
On[Assert] (* aktivuj Assert *)
Assert[x == "ret"] (* pokud x != "ret", tak vypíše hlášku *)
Assert[x == "ret", "neni ret"] (* doplňovací text "neni ret" *)
Off[Assert] (* deaktivuj Assert *)
Ve výchozím nastavení jsou výrazy |
Varování | import warnings # nutno importovat modul warnings
# nějaký kód...
warnings.warn("Text varování") # vypiš varovné hlášení
# nějaký další kód...
Modul |
(* definuj text chybové hlášky přidružené k symbolu fce *)
fce::jmenohlasky = "Text hlášky s parametrem ``.";
(* nějaký kód... *)
Message[fce::jmenohlasky, 42]; (* vypíše hlášení: "Text hlášky s parametrem 42" *)
(* nějaký další kód... *)
Přístup WL k varováním a výjimkám je odlišný od toho v Pythonu a |
Výjimky | # nějaký kód...
try:
# nějaký kód v němž může dojít k chybě...
raise ArithmeticError # anebo lze vyvolat výjimku ručně
# nějaký další, nevyhodnocený, kód
except ArithmeticError:
# kód obsluhy výjimky
else:
# proběhne-li vše bez chyby, vykonej tento kód
finally:
# v každém případě nakonec ale vykonej tento kód
Výjimky jsou představovány třídami různých typů, které vytváření stromovou strukturu vycházející z kořenové výjimky |
(* chybová hlášení *)
f::jmenoch = "Nastala chyba!";
Check[
(* nějaký kód v němž může dojít k chybě... *)
(* anebo lze vyvolat hlášku ručně: *)
Message[f::jmenoch]
(* pokračuje se ve vyhodnocování kódu... *)
, alterVyraz, f::jmenoch]
(* zachytí jen chybové hlášky typu f::jmenoch a vrátí hodnotu alterVyraz *)
(* přerušení vyhodnocování uživatelem *)
CheckAbort[
(* nějaký kód... *)
(* přeruš vyhodnocování; lze i klávesovou zkratkou Alt + `.`: *)
Abort[]
(* nějaký další, nevyhodnocený, kód *)
, alterVyraz]
(* zachytí Abort a vrátí hodnotu alterVyraz *)
(* nízkoúrovňová varianta... *)
Catch[
(* nějaký kód... *)
(* přeruš vyhodnocování kódu: *)
Throw[vyraz, tag]
(* nějaký další, nevyhodnocený, kód... *)
, tag]
(* zachytí jen ty výrazy Throw, jejichž druhý parametr je tag, a vrátí hodnotu vyraz *)
(* vysokoúrovňová varianta... *)
Enclose[
(* nějaký kód... *)
(* pokud vyraz nesplňuje podmínku podm, přeruš vyhodnocování kódu: *)
ConfirmBy[vyraz, podm]
(* nějaký další, nevyhodnocený, kód *)
]
(* vrať objekt Failure obsahující informace o chybě *)
(* Enclose lze uzpůsobit i tak, aby bral jen výjimky o daném tagu *)
Chybová hlášení vyvolaná funkcí |
Úklid kódu | with open("soubor.txt", "r") as file:
# kód manipulující s objektem file...
# pokud "soubor.txt" nelze otevřít či dojde k chybě při přístupu k datům,
# není vyvolána podmínka a při opuštění bloku with je soubor zavřen a uvolněn z paměti
|
WithCleanup[
(* inicializační kód *)
file = OpenRead["soubor.txt"]
,
(* hlavní blok kódu manipulující s objektem file... *)
,
(* kód, jenž se vyhodnotí bez ohledu na to, nastala-li v hlavním bloku chyba, či nikoliv *)
Close[file]
]
Funkce |
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.