Kezdőoldal » Számítástechnika » Programozás » Pythonban tényleg így kell...

Pythonban tényleg így kell csinálni? Nem akarom elhinni.

Figyelt kérdés

Van egy nagy adattömböm (t), keresek benne egy x értéket, ill. annak pozícióját:

pozicio = t.index(x)

De ha x nem szerepel t-ben, akkor hibaüzenettel elszáll, tehát előtte még kell (???):

if x in t vagy if t.count(x)>0 (???)

Kétszer kell megkerestetni? Miért nem ad vissza pl. -1-et a t.index(x), ha nincs benne, ahelyett hogy kiakadna?



2018. dec. 18. 12:09
1 2
 11/20 anonim ***** válasza:

Pedig de, a kivételkezelés az ajánlott mód.

Nem tudom, tudsz-e PHP-ül, de ott

- egyes függvények 0-t/false-t adnak vissza, ami hibát jelez

- más függvényeknél a 0 a végeredményt jelenti

- megint más függvényeknél a 0 végeredményt jelent, míg a logikai false jelenti a hibát


Ez az egyik oka, hogy lehetőleg kerülni kell, hogy a függvény visszatérési értékében a végeredményen kívül bármi mást is visszaadjon. A kivételes esetek (hibák, váratlan eredmények, stb.) kezelésére a kivételkezelést kell használni.

2018. dec. 18. 18:41
Hasznos számodra ez a válasz?
 12/20 anonim ***** válasza:

Más nyelvekben:

* Java List.indexOf():

[link]

* C# Array.indexOf():

[link]

* Javascript Array.indexOf():

[link]

* Ruby: Array.index():

[link] - bár itt -1 helyett nil jön vissza

* Perl: first_ndex:

[link]


feltételezem a kedves kérdező ezért keres hasonlót Pythonban

2018. dec. 18. 19:10
Hasznos számodra ez a válasz?
 13/20 anonim ***** válasza:

#4: "Mert én vettem a fáradságot és igen.( Külön mértem a futási időt python-nal)"


Nem írtad le hogy mérted, mert nekem eléggé gyanús az állításod, a ténylegesen dobott exception minden nyelven nagy overheaddel jár.


Én az alábbi kódot használtam tesztelésre:


#python 3.5.2

import time



x = [0,1,2,3,4]


now = time.time()


y = -1


i = 1

while i < 1000000:

  try:

    y = x.index(4)

  except ValueError:

    pass

  i += 1


timeDiff = time.time() - now


print (str(y) + ', ' + str(timeDiff))


Majd ezuán az index(4)-et árírtam index(5)-re


Az eredmény nem meglepően az, hogy ha expteption jön, akkor 3x-os a futási idő.


Ezen az oldalon teszteltem: [link]

2018. dec. 18. 20:02
Hasznos számodra ez a válasz?
 14/20 anonim ***** válasza:

"Nem írtad le hogy mérted, mert nekem eléggé gyanús az állításod, a ténylegesen dobott exception minden nyelven nagy overheaddel jár."


Python shell-be csak bedobáltam lambdákkal, külön el se mentettem. Meg azt hogy mit miután hányszor kell lefuttatni egy jó részét csak manuálisan végeztem el. Annak pontos elmagyarázása több munka lenne mint elegánsan megírni. Meg nem is biztos hogy elsőre sikerülne úgy, hogy tényleg precíz legyen. Csak a leglényegibb rész letesztelésére mentem rá minél kevesebb emberi erőforrás ráfordítással. (Vagyis erre optimalizáltam. Mj.: Ettől függetlenül, de mégis valamilyen szinten ide sorolható, hogy sok esetben (közel se mindig) a Python gyorsabb mint a C. Ugyanis az emberi tényezőt is figyelembe kéne venni amiről el szoktak felejtkezni gyakran. Ha gyorsba le kell generálni valamit / kiszámolni valamit, aztán többet nincs rá szükség (illetve ha mégis lenne valamikor akkor gyorsabb újra megírni mint megkeresni a kódot, hiszen rengeteg ilyen gyorsan összedobott spec. célkód előfordul nálam) a ráfordított emberi idővel együtt ha gyorsabban eredményre jutottam mint c-ben akkor én gyorsabbnak tekintem, de ez csak egy sarkosított esetfajta volt, nem csak ekkor gyorsabb illetve kevésbé költséges, ahol a költség mit jelent most nem definiálom, anyagi vagy humán erőforrás stb. lehet.)

Igazából vakon is megmondtam volna amit állítottam a futási időről múltkor, csakhogy mégis empirikusan ellenőrizzem mielőtt ezt állítom e miatt vettem rá a fáradságot.


"Az eredmény nem meglepően az, hogy ha expteption jön, akkor 3x-os a futási idő."


Ránézésre is több a futási ideje avagy alsó becsléssel annyi mint 2x végigmenni rajta, mintha in operátorral ellenőrizném kivételkezelés helyett. Ezzel azt a hamis képet keltve a felületes szemlélőnek mintha az in lenne mindig a jó választás ha futási időre akarunk optimalizálni.

Rossz oldalról közelítetted meg a kérdést, bizonyos szempontból az is jó oldal ugyan. A kérdés nagy tömbben (listában) való keresésről szól. Te meg csinálsz tesztet kis tömbre. Ad bizonyos overhead-ot a kivételkezelő mechanizmus, de ez nem követi azt a lineáris futási idő növekedést a tömb méretének növelésével mint a keresési idő növekedése (legrosszabb esetben). A domináns tényező a keresési idő és nem a kivételkezelés, ha a tömb méretét a végtelenbe tartatom (futási idő elemzés során). Ugyanakkor meg az in operátorral ha helyettesítem a kivételkezelést akkor az minden tömb mérettartományba hozzárak még egy tagot ami szintén lineáris függvénye a tömb méretének ami szintén egy domináns tag lesz, ami meghatározó a futási idő szempontjából.


"Kézzel fogható" tesztet is csináltam hozzá, de ezt csak ma: pastebin (pont) com/gX5XV1py

Ha isRandom az True értékű akkor egyenletes eloszlású randommal feltölti a tömböt amire utaltam múltkor, ez ugyan lassabb folyamat a random generátor futási ideje miatt, szemben mintha isRandom False lenne. Ha gyorsan kell akkor random nélkül gyorsabban létrehozza a tömböt ugyan, de nincsennek random elemek keresése melyek a tömbben random helyen vannak.


RunTimeTest0 esetében semmi hibakezelés, ahol vakon elhisszük hogy mindig csak olyat keresünk ami benne van a tömbben. Csak ilyet is kerestetünk vele.

RunTimeTest1 esetében kivételkezelés van, olyan esetnek is kitesszük amikor olyat kell kerednie ami nincs is a tömbben.

RunTimeTest1 esetében in operátorral ellenőrizzük hogy van e olyan elem a tömbben, olyan esetnek is kitesszük amikor olyat kell kerednie ami nincs is a tömbben.


Úgy írtam meg, hogy Python-vel és Python3-al is kompatibilis legyen. Saját gépemen teszteltem.

2018. dec. 19. 13:29
Hasznos számodra ez a válasz?
 15/20 anonim ***** válasza:

"RunTimeTest1 esetében in operátorral ellenőrizzük hogy van e olyan elem a tömbben, olyan esetnek is kitesszük amikor olyat kell kerednie ami nincs is a tömbben."

Javítás:

RunTimeTest2 esetében in operátorral ellenőrizzük hogy van e olyan elem a tömbben, olyan esetnek is kitesszük amikor olyat kell kerednie ami nincs is a tömbben.

2018. dec. 19. 13:32
Hasznos számodra ez a válasz?
 16/20 anonim ***** válasza:

Jó, ezzel egyetértek, viszont akkor már csak az a kérdés, hogy mi a "nagy" definíciója.


OK, lehet a 5-tel picit kis példát vettem, de még 1000 elemre is látszik az exception overheadje.

Nyilván egy 8 milliós tömbben nem fog keresni elemeket valaki gyakran, erre jobb adatszerkezetek vannak. (Legalábbis gondolom hogy Pythonban is van valami hashset vagy hasonló)

2018. dec. 19. 15:15
Hasznos számodra ez a válasz?
 17/20 anonim ***** válasza:

Sose kerestem így egyébként meg nem is akartam belemenni, hogy más adatszerkezet használata előnyösebb a keresésre.

Dictonory-vel (dict) meg lehet oldani végül is ami "alap tartozék" (ennek megfelelően kell lekódolni), ami egyébként hasítótábla a belső implementációban. Mint szinte mindennek ennek is meg vannak az előnyei, hátrányai. Az a nagy ötlet ebben az adatszerkezetben, hogy a keresési idő konstans, nem nő az adatszerkezet méretével, kivételdobás esetén is a kivétel az is csak egy konstans tagot ad hozzá. Viszont nem garantált a konstans keresési idő, ez a hash ütközésektől függ hogy mennyi lesz, de próbál eléggé randomizált szerűen eloszlani, legrosszabb esetben egy kostans szorzófaktor erejéig ekvivalens egy listában lévő legrosszabb keresési idővel. Nem pl. az AVL fa belső implementációja mellett döntöttek a python implementáló, ami viszont logaritmikus keresési idejű (az adatszerkezet logaritmusával arányos idejű) és garantáltan nem több mint c*gyök(2)*log(n) keresési idejű, ahol c egy konstans tag n az adatszerkezet mérete.

Konkrét célfeladatokra egyébként lehet még gyorsabb adatszerkezeteket is csinálni mint a beépített adatszerkezetekkel ami elérhető lenne Pythonba, de ekkor meg a Python rugalmasságát veszítjük el és igen nagy munka is lehet, le lehet menni natív kódba is.

2018. dec. 19. 19:10
Hasznos számodra ez a válasz?
 18/20 anonim ***** válasza:

"az adatszerkezet logaritmusával arányos idejű"

Mármint az adatszerkezet méretének logaritmusával arányos idejű.

2018. dec. 19. 19:11
Hasznos számodra ez a válasz?
 19/20 A kérdező kommentje:

Nem is kell más programnyelvekben keresni, a Pythonban is megvan (Help, részlet):

"str.find(sub[, start[, end]])

Return the lowest index in the string where substring sub is found, such that sub is contained in the slice s[start:end]. Optional arguments start and end are interpreted as in slice notation. Return -1 if sub is not found."

Az str is egy tömb/string/füzér/szekvencia. És úgy látszik itt nem zavar a -1, nem az utolsó elemet jelenti. Hááát ...

2019. febr. 4. 15:11
 20/20 Ozmium42 ***** válasza:

A -1 mindenképpen az utolsó elemet jelenti, de a find metódus soha nem fog negatív értéket találni, mert 0-ról indul felfelé. A -1, mint hibajel, itt is problémás, mert hát a string-ekre is igaz, hogy string[-1] az utolsó elemre mutat. Persze ha külön figyelsz erre, és nem próbálod ellenőrzés nélkül felhasználni ezt a visszatérési értéket indexként, akkor OK.


Még azt megpróbálhatod, hogy írsz egy saját osztályt, ami megörökli a beépített list osztályt, de átírod az index methodot, amire akarod.

2019. febr. 4. 15:52
Hasznos számodra ez a válasz?
1 2

Kapcsolódó kérdések:




Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu

A weboldalon megjelenő anyagok nem minősülnek szerkesztői tartalomnak, előzetes ellenőrzésen nem esnek át, az üzemeltető véleményét nem tükrözik.
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!