r2d290 Skrevet 30. mai 2011 Del Skrevet 30. mai 2011 Heisann Jeg er relativt ny i Python, og lurte på om noen kunne hjelpe meg med å få til en teller. Jeg ønsker at hver gang jeg kommer inn i "else" skal "counter" øke med 1 (starte på 0). Verdien av counter skal deretter printes ut (print "programmet har gått inn i else " + counter + " ganger." Jeg har kommet frem til at jeg må angi at counter=0 rett ovenfor for-løkka nederst, hvis ikke blir den nullstilt hver gang for-løkka går. Men jeg sliter med å få returnert den nye verdien av counter fra write-klassen... Jeg har følgende utsnitt av en kode: class write: def impWrite(self,prog): self.prog = prog . . . if findPatTitle[0] == version2: print name2 + updated else: print outdated1 + name2 + outdated2 + version2 + outdated3 + findPatTitle[0] . . . for i in range(1, linjer+1): Nr = str(i) programNewline = getIndex.readline() program = programNewline.rstrip('\n') prog = program programObject=write() programObject.impWrite(prog) Lenke til kommentar
etse Skrevet 31. mai 2011 Del Skrevet 31. mai 2011 Legg variabelen du skal øke inn I selva klassen ig sett den til 0 i konstruktøren. Deretter kan du øke den med en hver gang du havner I elsen. Lenke til kommentar
Terrasque Skrevet 11. juli 2011 Del Skrevet 11. juli 2011 Humm.. Et par merkelige ting der... Først og fremst, hvorfor lager du en ny class instance i hver loop? Og hva med "prog = program" ? Og, fra det eksemplet du viser, ser jeg ikke noen grunn til at impWrite er inne i en class definisjon, istedet for en vanlig funksjon. Uansett, er fire måter å gjøre det du spør om, som jeg kommer på i farten. 1. Bruke en global variabel 2. Bruke en class variabel (og ikke lage ny class instance hele tiden) 3. Bruke en static class variabel (litt hårete) 4. få impWrite til å returnere en verdi som indikerer om else var kjørt, og holde orden på det i for-løkken Lenke til kommentar
torbjørn marø Skrevet 11. juli 2011 Del Skrevet 11. juli 2011 (endret) class Foo: def __init__(self): self.else_count = 0 self.do_else = False def bar(self): if not self.do_else: print "if..." else: self.else_count += 1 print "else %s ganger" % self.else_count self.do_else = not self.do_else foo = Foo() for i in range(1, 10): foo.bar() Output: if... else 1 ganger if... else 2 ganger if... else 3 ganger if... else 4 ganger if... Endret 11. juli 2011 av torbjørn marø Lenke til kommentar
r2d290 Skrevet 11. juli 2011 Forfatter Del Skrevet 11. juli 2011 Takker for svar =) Glemte å si at jeg fikk det til ved å la det som sto inni write-klassen skje rett i for-løkka. Gjorde det sånn i mitt nybegynnende forsøk på å holde ting ryddig og adskilt, men fant ut at det var best å la det være =) Lenke til kommentar
snippsat Skrevet 11. juli 2011 Del Skrevet 11. juli 2011 (endret) Enkel og fin løsning torbjørn. En mere universell vil være og skrive en counter class. Da kan man bare sette in counter() i den blokken man ønsker telling. Tar litt om dette. class Counter(object): def __init__(self, fvalue=0, inc=lambda x: x + 1): self.inc = inc self.val = fvalue def __call__(self): old = self.val self.val = self.inc(self.val) return old class foo(object): def bar(self, num, counter): if num < 5: return 'Less than 5' else: return 'More than 5 count %s' % counter() Tester ut i IDLE. >>> counter = Counter(1) >>> f = foo() >>> for i in range(10): ... f.bar(i, counter) ... 'Less than 5' 'Less than 5' 'Less than 5' 'Less than 5' 'Less than 5' 'More than 5 count 1' 'More than 5 count 2' 'More than 5 count 3' 'More than 5 count 4' 'More than 5 count 5' >>> Vi ser Counter class fungerer fint i else blokken. Kan lagre kun Counter class(counter.py i pythonpath) og importere den når vi trenger telling. from counter import Counter class foo(): def bar(self, num, counter): if num < 5: return 'Less than 5' else: return 'More than 5 count %s' % counter() Teste ut,og denne gangen teste og telle ned. >>> counter = Counter(-5) >>> f = foo() >>> for i in range(10): ... f.bar(i, counter) ... Less than 5 Less than 5 Less than 5 Less than 5 Less than 5 More than 5 count -5 More than 5 count -4 More than 5 count -3 More than 5 count -2 More than 5 count -1 >>> Endret 11. juli 2011 av SNIPPSAT 1 Lenke til kommentar
torbjørn marø Skrevet 11. juli 2011 Del Skrevet 11. juli 2011 Ooooohh, nice SNIPPSAT! Har ikke sett __call__(self) før, den likte jeg. Objekter er altså også funksjoner i Python?! Om noen et øyeblikk trodde jeg behersket Python så tok de alvorlig feil Lenke til kommentar
Terrasque Skrevet 11. juli 2011 Del Skrevet 11. juli 2011 (endret) hehe, er mye gøy man kan gjøre med de der >>> class moo(dict): def __getattr__(self, name): return self.__dict__.get(name, None) def __setattr__(self, name, value): self.__dict__[name] = value def __delattr__(self, name): del self.__dict__[name] >>> m = moo() >>> m.asd >>> m.asd = "ossom" >>> m.asd 'ossom' >>> del m.asd >>> m.asd >>> Et annet triks: >>> class lurings(object): bla = [0] def __call__(self): self.bla[0] = self.bla[0] + 1 def getval(self): print self.bla[0] >>> for x in range(20): lurings()() >>> lurings().getval() 20 >>> Edit: Ble litt gira her, så et par andre triks: >>> ' '.join([str(x) for x in range(41) if x%2==0]) '0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40' >>> def evens(x): i = 0 while i <= x: yield i i = i + 2 >>> for x in evens(40): print x, 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 >>> for x in evens(40): print x%3 == 0 and x or x > 9 and "__" or "_", _ _ _ 6 _ __ 12 __ __ 18 __ __ 24 __ __ 30 __ __ 36 __ __ >>> Endret 11. juli 2011 av Terrasque Lenke til kommentar
snippsat Skrevet 11. juli 2011 Del Skrevet 11. juli 2011 Python har flere funksjoner som en klasse kan kalle på seg selv. Kan bryte det ned litt. >>> c = Counter() #__init__ get run now,acts as an constructor >>> dir(c) ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'inc', 'val'] >>> c() #Now when we do a call with() __call__ will run 0 >>> c() 1 >>> c.__call__() 2 >>> c() 3 >>> Viss vi skriver om __call__ og bruker et vanlig navn. class Counter(object): def __init__(self, fvalue=0, inc=lambda x: x + 1): self.inc = inc self.val = fvalue def call_me(self): old = self.val self.val = self.inc(self.val) return old >>> c = Counter() #__init__ get run,acts as an constructor >>> c() Traceback (most recent call last): File "<interactive input>", line 1, in <module> TypeError: 'Counter' object is not callable >>> #Python do not find any __call__ method #Have to call it with name >>> c.call_me() 0 >>> c.call_me() 1 >>> c.call_me() 2 >>> Tar med en til med __call__ her også med "special method" __str__ Alle __something__ er "special method" i python. class Animal(object): def __init__(self): self.stomach = [] def __call__(self,food): self.stomach.append(food) def __str__(self): '''return a human-readable string''' return 'In stomach %s' % (self.stomach) >>> dog = Animal() #__init__ >>> dog('beef') #__call__ now with one argument >>> print dog #__str__ In stomach ['beef'] >>> dog('Cat') >>> print dog In stomach ['beef', 'Cat'] >>> Lenke til kommentar
snippsat Skrevet 12. juli 2011 Del Skrevet 12. juli 2011 Edit: Ble litt gira her, så et par andre triks: Ja kan forsette litt ettsom det er litt stille i python delen. List comprehensions er en vanlig måte og skrive på i python og går ikke under triks kategorien lengere. ' '.join([str(x) for x in range(41) if x%2==0]) Viss vi skriver den om til en mer vanlig loop. >>> l = [] >>> for i in range(41): ... if i%2 == 0: ... l.append(str(i)) ... >>> ' '.join(l) '0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40' >>> Viss vi tar bort og konvertere til string. >>> [x for x in range(41) if x%2==0] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40] Så litt power med og bytte til generator expression,kun bytte [] til () >>> g = (x for x in range(41) if x%2==0) >>> g <generator object <genexpr> at 0x032AA968> >>> g.next() 0 >>> g.next() 2 >>> Hva er fordelen med dette? Med generator lese kun data som trenges inn til minnet. g.next() lese inn til minnet tømmes også videre. >>> g = (x for x in range(41) if x%2==0) >>> for i in g: ... print i, ... 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 Vi kan sende generator object inn i andre funksjoner. Si at vi vil legg til 5 på alle even tallene i generator objectet. def plusfive(gen): for n in gen: yield n + 5 g = (x for x in range(41) if x%2==0) for n in plusfive(g): print n, #5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 Dette var litt python power Lenke til kommentar
Terrasque Skrevet 12. juli 2011 Del Skrevet 12. juli 2011 (endret) Er ganske mange triks på http://stackoverflow.com/questions/101268/hidden-features-of-python Et trick som ble nevnt der, som jeg av og til bruker; decorators (eksempel kopiert fra siden) >>> def print_args(function): >>> def wrapper(*args, **kwargs): >>> print 'Arguments:', args, kwargs >>> return function(*args, **kwargs) >>> return wrapper >>> @print_args >>> def write(text): >>> print text >>> write('foo') Arguments: ('foo',) {} foo Ikke ofte jeg bruker, men utrolig nyttig i noen tilfeller Edit: Et annet triks jeg vil highlighte: def draw_point(x, y): # do some magic point_foo = (3, 4) point_bar = {'y': 3, 'x': 2} draw_point(*point_foo) draw_point(**point_bar) Også utrolig nyttig i noen tilfeller Endret 12. juli 2011 av Terrasque 1 Lenke til kommentar
r2d290 Skrevet 12. juli 2011 Forfatter Del Skrevet 12. juli 2011 Wow, you're way above my head now! But keep it goin Kanskje jeg kan se tilbake på dette engang når jeg blir mer erfaren ^^ Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå