[ StefanJer91 @ 18.04.2007. 19:13 ] @
Da ne bih otvarao novu temu odlucio sam da postavim nekoliko pitanja ovde. Naime, vec otprilike godinu dana programiram u pythonu, i jezik mi se jako svideo pre svega zbog lake sintaze i brzog programiranja u njemu. Cuo sam takodje da je za oko 30% brzi python2.5 od verzije 2.4 (Da li je to istina?). Ipak i dalje mi se cini sporim, ali nadam se da cu u buducnosti postati brzi posto me pre svega interesuje GameDev. Sledece pitanje je da li je Blender takodje napisan samo u pythonu (kod njega ne vidim neka usporenja i program veoma dobro funkcionise [bavim se i 3d modelovanjem u istom pa zato i kazem]). Sto se tice GameDev-a nisam bas apsolutni pocetnik posto sam imao vec prethodnog iskustva sa GM6 (1 godina otprilike), a sada polako zalazim u Tkinter i pygame(SDL-ov wraper za python). Zasto sam postavio ovo pitanje u vezi sa brzinom? Zato sto sam krenuo da pravim jedan program za crtanje pa mi je palo na pamet da ga uporedim sa paintom za pocetak. Rezultati nisu bili bas onakvi kakve sam ocekivo (prilozicu dole kod). Tacnije kada sam brzo povlacio misem primetio sam da python slabije za nekih 40% posto registruje kursor od painta pa crtez izgleda dosta grubo ( u to se mozete uveriti ako brzo nacrtate krug u oba programa). Da ne davim vise, evo koda i nadam se da cu dobiti odgovore na ova moja pitana.
Code:


from Tkinter import*


a=[] 
def crtanje(event):
    a.append((event.x,event.y))
    if len(a) > 2:
        a.remove(a[0])
    elif len(a) == 1:
        a.append(a[0])
    c.create_line(a, fill = 'black')

def gasi(event):
    for n in a:
        a.remove(n)


    

root = Tk()
f = Frame(root)

c= Canvas(root, width =640, height =480, bg = 'white')

c.bind('<Motion>', gasi)
c.bind('<Button1-Motion>', crtanje)
c.pack()
root.mainloop()



P.S. Ovo svakako nije program vec obican test, ali pokazuje nacin na koji sam to uradio

[Ovu poruku je menjao StefanJer91 dana 19.04.2007. u 20:44 GMT+1]
[ alex @ 20.04.2007. 14:24 ] @
Python 2.5 jeste brzi od verzije 2.4 - tacan procenat je relativno tesko oceniti jer se radi o poboljsanjima u nekoliko razlicitih sekcija, narocito u string operacijama i tzv. exception handling mehanizmu.

Sto se tice Blendera, koliko znam taj program nije napisan u Python jeziku vec ima u sebi integrisan Python interpreter za skriptovanje operacija.

Sad, sto se tice tvog primera, pokrenuo sam ga na mom Macu i nisam primetio nikakva usporenja niti grubost iscrtavanja - tvoj primer crta liniju siroku 1pixel i nema antialiasing tako da linija sama po sebi izgleda relativno grubo. Bilo bi zgodno kada bi poslao screenshot. (usput, kako si registrovao usporenje od 40% u odnosu na Paint?)

Inace, otvaranje nove teme je ocekivano i pozeljno, narocito kada se diskutuje o zasebnoj temi.
[ StefanJer91 @ 20.04.2007. 18:57 ] @
Ok, posto si ti admin mozes da otvoris temu pa premesti obe prethodne poruke.



Moze da se primeti kako se na radu napravljenom preko mog programa vide grublji uglovi dok u paintu toga nema (moj program sporije registruje kursor).
[ alex @ 23.04.2007. 10:21 ] @
Sredjivanje tema - poruke prebacene.
[ alex @ 23.04.2007. 12:05 ] @
Pre svega, tvoj primer je krajnje jednostavan, to moramo uzeti u obzir. Paint program, sem sto verovatno ima i antialiasing, takodje verovatno ima i tzv. smooth tehnike, cineci nacrtanu liniju meksom.

Evo slike tvog primera na mom racunaru - s obzirom da crta liniju izmedju svake dve tacke registrovanog pokreta misa, mora se ocekivati grubost. Takodje, mozda ima veze i do implementacije Tk biblioteke na Windows platformi, a i do brzine tvog racunara. Faktora ima mnogo.

[ StefanJer91 @ 23.04.2007. 12:54 ] @
Pa dobro, postoji li onda neki nacin da smooth-ujem liniju? Jos jedno pitanje: Da li je moguce u pythonu da napravim nesto ovako:
Code:

a = 5
def funkc():
   a = 8 # zelim da ovo a sada bude 8

print a # izbacuje vrednost 8 a ne 5

[ Dusan Marjanovic @ 23.04.2007. 13:15 ] @
Nisi baš jednoznačno opisao šta želiš, ali kapiram da varijablu hoćeš da proglasiš za globalnu, tj da ispred a u f-iji staviš keywork global
[ StefanJer91 @ 23.04.2007. 14:16 ] @
Ne. Zelim da variabla koja prodje kroz funkciju posle nje bude promenjena. Slicno kao kod referenci u c++
[ alex @ 23.04.2007. 15:07 ] @
Naravno da postoji nacin da se linija napravi meksom, za to ce ti biti potrebno malo matematike.

Sto se tice pitanja o globalnim varijablama, dovoljno je deklarisati varijablu kao globalnu, kao sto Dusan rece, sa global deklaracijom:

Code:

a = 5
def funkc():
   global a
   a = 8 # zelim da ovo a sada bude 8

print a # izbacuje vrednost 8 a ne 5


Mada, globalne varijable su po mom (i ne samo mom) misljenju stvar proslosti i ne bi trebalo da se koriste (sem u slucaju konstanti, sto je sasvim druga prica). Python je veoma moderan OO jezik i koriscenje arhetipskih konstrukcija kao sto su globalne varijable je potpuno nepotrebno. Preporucljivi refactoring tvog primera je sledeci:

Code:

a = 5
def func(a):
   a = 8

func(a)
print a


Funkcije, kao i klase, bi trebalo da vrse operacije samo na svojim, lokalnim varijablama, u svom scope-u, jer je uvek dozvoljeno (i preporucljivo) funkcijama proslediti instancu varijable kao argument ukoliko je potrebno vrsiti bilo kakve operacije nad tim varijablama. To su, sto bi se reklo, osnove programiranja.
[ StefanJer91 @ 24.04.2007. 13:30 ] @
Izgleda da me ponovo niste razumeli. U kodu koji je postavio alex, a je u funkciji = 8 ali njenim zavrsetkom ona ponovo postaje 5.

Code:

a = 5
def func(b):
   b = 8
   return b

a = func(a)


Znaci treba mi nesto kao primer iznad ali da nemoram da koristim ovo a = func(a)
[ StefanJer91 @ 24.04.2007. 16:52 ] @
Evo jos nesto u vezi brzine

Code:

# pygame
import pygame

a = pygame.image.load('slika.bmp')
width = a.get_width()
height = a.get_height()

for y in xrange(height):
   for x in xrange(width):
      color = a.get_at((x,y))
      a.set_at((x,y),(255-color[0],255-color[1],255-color[2]))

pygame.image.save(a, 'izlaz.bmp')


Code:

#PIL
import Image
a = Image.open('slika.bmp')

width = a.size[0]
height = a.size[1]

for x in xrange(width):
   for y in xrange(height):
       color = a.getpixel((x,y))
       a.putpixel((x,y),(255-color[0],255-color[1],255-color[2]))
       

a.save('abc.bmp')


Ovako: Ovo je jedan isti program napravljen pomocu 2 razlicita modula pygame i PIL-a(Python Image LIbrary). Program otvara sliku i pravi njenju kopiju ali sa negativnim bojama. U pygamu programu treba nesto vise od 6 sec. na mom kompu dok PIL-u (na veliko iznenadjenje) oko 15 sec! Ovo je svakako previse, posto paint odradi isti posao za manje od sekunde.
Da li neko od vas ima iskustva sa PIL-om i da li bi znao da ovo uradi na brzi i bolji nacin?
[ alex @ 24.04.2007. 17:47 ] @
Citat:
StefanJer91: Izgleda da me ponovo niste razumeli. U kodu koji je postavio alex, a je u funkciji = 8 ali njenim zavrsetkom ona ponovo postaje 5.


Moja greska - razmisljao sam u Javi a pisao program u Pythonu :) - Python prosledjuje varijable funkcijama po vrednosti a ne referenci. Posto su sve u pitanju objekti, prosledjuje se kopija objekta - u gore-spomenutom slucaju se promena u okviru funkcije menja samo kopiju varijable u okviru same funkcije. To je nesto sto cesto zbunjuje novopecene python programere koji dolaze iz C ili Java sveta.

Sa objektima i njihovim member varijablama je naravno drugacije.

Evo i jednog primera, ilustracije radi:
Code:



def func(b):
    b = 8

def gfunc():
    global a
    a = 20
    
def funcret():
    return 8


class Klasa:
    a = 5
    
    def func(self):
        self.a = 20

a = 5

print "funkcije..."
print "na pocetku - ", a
func(a)
print "func(a) - ", a
gfunc()
print "gfunc - ", a
a = funcret()
print "funcret - ", a

print "objekti..."
ob = Klasa()
print ob.a
ob.func()
print ob.a


Kao sto se vidi, samo gfunc() funkcija menja samu varijablu (deklaracija global), dok se u prvoj funkciji nista ne dogadja. Funkcijom funcret() setujemo vrednost varijable putem vracanja vrednosti same funkcije - po mom misljenju, to je preporucljiv pristup.

Znaci, to sto ti zelis mozes izvesti sa global deklaracijom.
[ alex @ 24.04.2007. 17:54 ] @
Citat:
StefanJer91:
Ovako: Ovo je jedan isti program napravljen pomocu 2 razlicita modula pygame i PIL-a(Python Image LIbrary). Program otvara sliku i pravi njenju kopiju ali sa negativnim bojama. U pygamu programu treba nesto vise od 6 sec. na mom kompu dok PIL-u (na veliko iznenadjenje) oko 15 sec! Ovo je svakako previse, posto paint odradi isti posao za manje od sekunde.
Da li neko od vas ima iskustva sa PIL-om i da li bi znao da ovo uradi na brzi i bolji nacin?


Hm, mislim da je tvoj primer daleko od efektivnog, narocito ako je u pitanju veliki format slike - stavise, siguran sam da i PIL i pygame imaju API poziv za kreiranje negativa.

Nisi odgovorio koji racunar imas? Zvuci mi neverovatno da je PIL-u potrebno 16 sekundi za tako nesto..
[ bzero @ 24.04.2007. 17:56 ] @
putpixel() je relativno spor i ne treba ga koristiti kada treba da se menja velik broj pixela, ili svi kao u ovom slucaju. Probaj ovako nesto, trebalo bi da bude mnogo brze:

Code:

from PIL import Image

im = Image.open("slika.bmp")

out = im.point(lambda i: 255 - i)
out.save('abc.bmp')
[ StefanJer91 @ 24.04.2007. 18:31 ] @
@Bzero: Hvala, ovo je bilo ekstra brzo! Niej mi bas najasnija ova funkcija point... Sta naprimer ako hocu da sliku napravim crno belom. Na onaj moj sporiji nacin bih znao, ali kako to da uradim preko pointa ili neceg drugog sto je adekvatno

@alex:
AMD Althon 64 2800+
512 MB of Ram
GeForceFx5200

Nije bas 16 vec nekih 13-14 ali je i to bilo svakako previse



[Ovu poruku je menjao StefanJer91 dana 24.04.2007. u 19:43 GMT+1]
[ bzero @ 25.04.2007. 10:06 ] @
Ako hoces da dobijes crno belu sliku pretpostavljam da je najbolje da koristis convert():

Code:

from PIL import Image

im = Image.open("slika.bmp")
im = im.convert("L")
im.save("crnobelo.bmp")


Mada generalno, mislim da je najbolje da prvo proucis PIL handbook, tu imas opis svih modula, funkcija i dosta konkretnih i korisnih primera. Puno stvari mozes naci i ovde: http://mail.python.org/mailman/listinfo/image-sig
[ alex @ 25.04.2007. 11:32 ] @
Citat:
StefanJer91:
@alex:
Nije bas 16 vec nekih 13-14 ali je i to bilo svakako previse


Kao sto bzero rece, prouci PIL handbook - narocito ImageOps modul, za transformacije Image objekata:

Code:

from PIL import Image, ImageOps

image = Image.open('slika.bmp')
# nimage je negativ
nimage = ImageOps.invert(image)
nimage.save('negativ slika.bmp')


Nisam uporedjivao brzinu, al' trebalo bi da je veoma brzo :).

Zakljucak: tvoji primeri nisu iskljucivo problem Python jezika ili interpretera, vec neefikasnog primera.
[ StefanJer91 @ 25.04.2007. 16:31 ] @
Ok, hvala evo uzeo sam da prelistavam pil handbook, kada zatreba pomoc trazicu:) Inace, niste mi odogovorili koliko je python pogodan za GamDev i da li se razvija u tom pravcu?
[ alex @ 25.04.2007. 17:58 ] @
GameDev, kazes? Evo, pitaj CCP Games koji napravise Eve-Online, najuspesniju MMORPG igru - da nije Pythona, tacnije stackless verzije igra ne bi bila ono sto jeste - sve osim 3D engine-a je uradjeno u python jeziku + kompletna pozadina (server side) igre.

Sve u svemu, python je izuzetno podoban za razvoj igara. Stackless-om se bavim vec par godina i neverovatno je koliko je mocan i jednostavan za concurrent programiranje. Trenutno se igram sa integracijom sa G3D open source 3d engine-om i lakoca integracije pythona je veoma impresivna.

[ Au197/79 @ 25.04.2007. 18:30 ] @
Citat:
alex: Moja greska - razmisljao sam u Javi a pisao program u Pythonu :) - Python prosledjuje varijable funkcijama po vrednosti a ne referenci. Posto su sve u pitanju objekti, prosledjuje se kopija objekta - u gore-spomenutom slucaju se promena u okviru funkcije menja samo kopiju varijable u okviru same funkcije. To je nesto sto cesto zbunjuje novopecene python programere koji dolaze iz C ili Java sveta.


Izvinjavam se na digresiji (možda je ovo tema za novi thread) ali ja sam živo u uverenju da je prenos parametara u javi i pythonu identičan. Zar i u jednom i u drugom slučaju nije prenos po vrednosti? Samo je razlika što su sve u pythonu predstavlja preko referenci a u javi postoje i prosti tipovi, ali u oba slučajeva vrednost promenjive stvarnog argumenta se kopira u formalni parametar. U suštini dobija se kopija reference na objekat (osim za javine proste tipove), a sam objekat se ne kopira.
[ alex @ 26.04.2007. 10:57 ] @
Python prenosi varijable preko vrednosti, a ne referenci. Takodje, Python prenosi varijable preko referenci, ne vrednosti. Sad, kako je to moguce?

Odgovor na to se moze naci u tome kako ko shvata pojam "prenos varijable preko reference" - u pythonu, sve varijable su interno prezentovane kao adrese (ka delu memorije gde su cuvane) i te adrese se prenose preko vrednosti te adrese. To se moze shvatiti i kao prenos vrednosti a i kao prenos reference (adresa je referenca). U oba slucaja, znaci istu stvar. Ergo, obe tvrdnje sa pocetka moje poruke izgledaju kao tacne (zavisno kako ko shvata pojam reference).

Dalje, pojam prenosa varijabli u python jeziku je specifican. Govorimo o imenima i dodeli - kada se varijabla dodeli funkciji kao argument, to je u sustini dodela vrednosti varijable novom imenu varijable (u lokalnom namespace-u funkcije), tako da ce to novo ime da ima vrednost originalnog objekta. Kada izvrsimo dodelu nove vrednosti tom imenu u samoj funkciji, to ime se jednostavno vezuje za novu vrednost.

Sad, konfuzija nastaje kod Python tipova - python sadrzi mutable i imutable tipove. Python imutable tipovi (kao sto se vidi u gorespomenutim primerima) se ne mogu menjati i vezivanje nove vrednosti fakticki kreira novi imutable objekat sa novom vrednoscu, i originalan objekat se ne menja, dok se mutable tipovi (list, dict i objekti) mogu menjati u funkcijama u kojima su preneti (jer je promena vrednosti vidljiva svim imenima/varijablama kojima je dodeljena ta vrednost!).

No, s obzirom na prirodu python jezika, ova konfuzija i ne bi trebalo da bude problem, jer sâm jezik maltene forsira programera da postuje OO principe programiranja.

Na python mailing listi se moze naci veliki broj diskusija na tu temu i ima dosta veoma kvalitetnih objasnjenja, ukoliko zelite vise informacija.
[ StefanJer91 @ 20.05.2007. 14:26 ] @
Ljudi jel za neko kako da odredim broj decimala koje treba da se ispisu posle broja? Npr imam broj 6.2423465446 i zelim da imam 3 decimale i on izbaci 6.242
[ Au197/79 @ 20.05.2007. 22:00 ] @
Imaš u dokumentaciji kad otvoriš index pa prva stavka "% formating", a imaš i u tutorijalu o input i output-u.
Konkretno tebi treba nešto ovako:
Code:
print "%.3f" % (10.0/3)

Ovde imaš string koji je prazan i u njemu mesto za broj (to je ono %.3f i to se ne pojavljuje u stringu) formatirano sa slovom f za float a .3 znači da iza decimalnog zareza ima samo 3 mesta. Onaj drugi % znači da se mesta u stringu ispred njega popunjavaju elementima liste iza % (u ovom slučaju imamo samo 1 element).
[ StefanJer91 @ 21.05.2007. 13:41 ] @
Hvala ti za ovo ali sta da radim ako mi treba 100 i vise decimala?
[ alex @ 22.05.2007. 15:01 ] @
Procitaj Python dokumentaciju, pre svega - odgovore na tako osnovna pitanja uvek mozes prvo naci u dokumentaciji. Recimo, ovde:
Citat:

For safety reasons, floating point precisions are clipped to 50;


Python prompt koristi repr() funkciju, koja ima ogranicenu preciznost na 17 decimala. Ukoliko zelis vecu preciznost, postoji nekoliko nacina, jedan od kojih je implementacija svoje klase za float brojeve.
[ StefanJer91 @ 22.05.2007. 20:22 ] @
Ne razumem najbolje. Mozes li ako nije problem da postavis kod za npr. 40 decimala?
[ alex @ 23.05.2007. 10:07 ] @
Nesto mi govori da me nisi poslusao i procitao dokumentaciju.

Code:

print "%.40f" % (10.0/3)


Da li je sad jasnije?
[ StefanJer91 @ 23.05.2007. 12:43 ] @
Ne. On mi izbaci 3.3333333333333335000000000000000000000000, a treba mi 3. (39 decimala od 3 pa na kraju 7)