473,326 Members | 2,136 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Function to execute only once

Hi if I have a function called
tmp=0
def execute():
tmp = tmp+1
return tmp

also I have
def func1():
execute()
....
and
def func2():
execute()
....

now I want execute() function to get executed only once. That is the
first time it is accessed.
so taht when funcc2 access the execute fn it should have same values as
when it is called from func1.

Oct 14 '05 #1
9 9255
If I understand you correctly, you want `tmp' to be global...

If so, declare it as so in execute ->

def execute():
global tmp
tmp = tmp+1
return tmp

Otherwise, what happens is that you declare a variable local to
execute, that is named tmp. When the assignment occurs it uses the
global value of `tmp', which is 0, and adds it to the *local* tmp.

I hope that is not too confusing.

jw

On 14 Oct 2005 12:11:58 -0700, PyPK <su*******@gmail.com> wrote:
Hi if I have a function called
tmp=0
def execute():
tmp = tmp+1
return tmp

also I have
def func1():
execute()
....
and
def func2():
execute()
....

now I want execute() function to get executed only once. That is the
first time it is accessed.
so taht when funcc2 access the execute fn it should have same values as
when it is called from func1.

--
http://mail.python.org/mailman/listinfo/python-list

Oct 14 '05 #2
"PyPK" <su*******@gmail.com> writes:
now I want execute() function to get executed only once. That is the
first time it is accessed.
so taht when funcc2 access the execute fn it should have same values as
when it is called from func1.


There's nothing built into Python for that. You have to program the
function to remember whether it's already been called. It sounds like
you're trying to avoid performing some side effect more than once.

Anyway, there's multiple ways you can do it. The conceptually
simplest is probably just use an attribute on the function:

tmp = 0 # you want to modify this as a side effect
def execute():
global tmp
if not execute.already_called:
tmp += 1
execute.already_called = True
return tmp
execute.already_called = False

Other ways include using a class instance, using an iterator, etc.

Generally too, you might find it cleaner to avoid having side effects
like that. Instead, put tmp itself inside a class instance:

class Memo:
def __init__(self):
self.value = 0 # any side effects operate on this
self.already_called = False

def __call__(self):
if not self.already_called:
self.already_called = True
self.value += 1
return self.value

execute = Memo()

Now you don't have global state cluttering things up, you can make
multiple instances easily, etc.
Oct 14 '05 #3
PyPK wrote:
now I want execute() function to get executed only once. That is the
first time it is accessed.


How about just calculating the value at import time?
--
Benji York
Oct 14 '05 #4
I've been seeing alot about decorators and closures lately and my
initial thought was that this would be a good place to use them instead
of wrapping it around a class. That was my initial thought :) What I
came up with was this:
def execute_once(fn):
result = None
def executor(*args, **kwargs):
if not result:
result = fn(*args, **kwargs)
return result
return executor

@execute_once
def execute(tmp):
tmp = tmp+1
return tmp

def func1(tmp):
execute(tmp)

def func2(tmp):
execute(tmp)

tmp=0
print 'init tmp:', tmp
func1(tmp)
print 'ran func1 tmp:', tmp
func2(tmp)
print 'ran func2 tmp:', tmp

It gives the following error:
init tmp: 0
Traceback (most recent call last):
File "C:\Download\test.py", line 26, in ?
func1(tmp)
File "C:\Download\test.py", line 19, in func1
execute(tmp)
File "C:\Download\test.py", line 5, in executor
if not result:
UnboundLocalError: local variable 'result' referenced before assignment

Makes sense to me, except I expected some closure 'magic'. I thought
that when I wrapped executor() inside execute_once() the name result
would be available to executor(). What am I missing here (I expect the
answer to be 'alot') but is this type of solution valid for this
problem?

Oct 14 '05 #5
The problem seemed to be because I was rebinding result inside
executor. Can someone explain why it works below but not in the first
one?

Also why is it if I set tmp as a global and don't pass it as a
paremeter to the various functions as per the OP that I get an
"UnboundLocalError: local variable 'tmp' referenced before assignment"?

def execute_once(fn):
print "in execute_once"
result = {}
def executor(*args, **kwargs):
if fn not in result:
result[fn] = fn(*args, **kwargs)
return result[fn]
return executor

@execute_once
def execute(tmp):
print "in execute"
tmp = tmp+1
return tmp

def func1(tmp):
return execute(tmp)

def func2(tmp):
return execute(tmp)

tmp = 0
print 'init tmp:', tmp
tmp = func1(tmp)
print 'ran func1 tmp:', tmp
tmp = func2(tmp)
print 'ran func2 tmp:', tmp
tmp = func1(tmp)
print 'ran func1 tmp:', tmp

OUTPUT:
in execute_once
init tmp: 0
in execute
ran func1 tmp: 1
ran func2 tmp: 1
ran func1 tmp: 1

Oct 14 '05 #6
"snoe" <ca*********@gmail.com> writes:
Also why is it if I set tmp as a global and don't pass it as a
paremeter to the various functions as per the OP that I get an
"UnboundLocalError: local variable 'tmp' referenced before assignment"?


If you don't declare it as a global, and if you try to assign a value
to it, then Python thinks it's a local. If you only refer to it and
never assign it, Python decides it's global. Python is weird that
way. One consequence is that if it's local to some outer scope, then
it's neither global nor local to your function, so there's no way to
assign to it.

I think Pythonic style is to not do complex things with closures,
but to use class instances instead.
Oct 14 '05 #7
"snoe" <ca*********@gmail.com> wrote:
I've been seeing alot about decorators and closures lately and my
initial thought was that this would be a good place to use them instead
of wrapping it around a class. That was my initial thought :) What I
came up with was this:


Apparently you're not the first to think of it:
http://aspn.activestate.com/ASPN/Coo.../Recipe/425445.

George
Oct 14 '05 #8
On 14 Oct 2005 12:11:58 -0700, "PyPK" <su*******@gmail.com> wrote:
Hi if I have a function called
tmp=0
def execute():
tmp = tmp+1
return tmp

also I have
def func1():
execute()
....
and
def func2():
execute()
....

now I want execute() function to get executed only once. That is the
first time it is accessed.
so taht when funcc2 access the execute fn it should have same values as
when it is called from func1.


You could have the execute function replace itself with a function
that returns the first result from there on, e.g., (assuming you want
the global tmp incremented once (which has bad code smell, but can be expedient ;-)):
tmp = 0
def execute(): ... global tmp, execute
... tmp = cellvar = tmp + 1
... def execute():
... return cellvar
... return tmp
... def func1(): ... return execute() # so we can see it
... def func2(): ... return execute() # so we can see it
... func1() 1 tmp 1 func2() 1 tmp 1 execute() 1 execute <function execute at 0x02EF702C> import dis
dis.dis(execute)

5 0 LOAD_DEREF 0 (cellvar)
3 RETURN_VALUE

But if you want to call the _same_ "execute" callable that remembers that
it's been called and does what you want, you need a callable that can
remember state one way or another. A callable could be a function with
a mutable closure variable or possibly a function attribute as shown in
other posts in the thread, or maybe a class bound method or class method,
or even an abused metaclass or decorator, but I don't really understand
what you're trying to do, so no approach is likely to hit the mark very well
unless you show more of your cards ;-)

Regards,
Bengt Richter
Oct 16 '05 #9
Bengt Richter wrote:
<snip>
>>> tmp = 0
>>> def execute():

... global tmp, execute
... tmp = cellvar = tmp + 1
... def execute():
... return cellvar
... return tmp

<snip>

On man did this put my head into a spin :P

--
Lasse Vågsæther Karlsen
http://usinglvkblog.blogspot.com/
mailto:la***@vkarlsen.no
PGP KeyID: 0x2A42A1C2
Oct 16 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Hagge | last post by:
I'm stuck in a problem Hi I want to create a funtion in asp. Like this Then the function convert the "custom tag" to. <a href=www.mypage.com/user/Smith>Smith</a> How to do? I'm real...
26
by: TomB | last post by:
I have a function on an "included" page. For reasons unknown to me I frequently will get an error - to the effect that the function can't be found. If I hit refresh/F5 it loads the page just...
3
by: domeceo | last post by:
can anyone tell me why I cannot pass values in a setTimeout function whenever I use this function it says "menu is undefined" after th alert. function imgOff(menu, num) { if (document.images) {...
15
by: John J | last post by:
I've written the following code into a class to search for and display the results of all races entered (The complete code is in a previous thread). I wish to amend the code so as to display the...
2
by: laredotornado | last post by:
Hello, I am looking for a cross-browser way (Firefox 1+, IE 5.5+) to have my Javascript function execute from the BODY's "onload" method, but if there is already an onload method defined, I would...
9
by: Kishor | last post by:
Hi all, I am Using VB.Net for developing my application. I am now needed help. In this project I have to execute some function, but I cannot call them directly using function name, I wanted to...
1
by: Timothy Perrigo | last post by:
(PostgreSQL 8.0 beta 4 on Mac OS X 10.3.6) I'm working on a function which creates and populates a temporary table, then returns the number of records it has inserted. I'm getting an error,...
4
by: Michael | last post by:
Hi, I'm having difficulty finding any previous discussion on this -- I keep finding people either having problems calling os.exec(lepev), or with using python's exec statement. Neither of...
2
by: Warex | last post by:
Hello, I have 2 questions maybe someone can answer. 1. On a function class when you return an item is it possible to return more than one and how is that done? Currently I am using for one...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.