Reputation: 53
def download():
upgrade = True
if upgrade:
# do a download using tftp
else:
# do a download via HTTP
As you can see, I have a hard coded value of upgrade that is set to true. In this script, it always does a tftp download.
How do I change the script to do tftp download at the first iteration and in the next iteration when the function download is called, it does a http download?
Upvotes: 1
Views: 720
Reputation: 2273
Since @Alex 's answer is good, but it need a extra step to construct an instance. You will also to store the instance globally.
So I made some change to it. Then you can import it and use it as function.
util.py
class Downloader(object):
_upgrade = False
@classmethod
def call(cls):
if cls._upgrade:
print('upgrade via http')
else:
print('download via tft')
cls._upgrade = True
def download():
Downloader.call()
main.py (using it)
from .util import download
download()
download()
This may not thread safe. And if you run it in different processes (e.g. webserver backend), you'd better use a remote storage for the flag (e.g. redis/oss).
Upvotes: -1
Reputation: 1
You could structure your code in the following:
def download(upgrade = False):
while upgrade == False:
print("HTTP")
break
print("TFTP")
download()
This will go through them once and exit the program after. The print statements are just a guide to show you what's happening and when it ends.
Upvotes: -2
Reputation: 41248
Probably you can (and should) just take this logic outside of your function, but if you want to pass the same argument each time but still change the behaviour after the first call, you could use the default mutable argument:
from itertools import count
def download(c=count()):
if next(c) == 0:
print('tftp')
else:
print('http')
download()
# tftp
download()
# http
download()
# http
download()
# http
The advantage of using itertools.count
rather than say a list is that you don't accumulate memory with each call.
Upvotes: 1
Reputation: 19124
For completeness here is the class
solution:
class Download(object):
def __init__(self):
self.executed = False
def __call__(self):
print('http' if self.executed else 'tftp')
self.executed = True
download = Download()
download() # tftp
download() # http
download() # http
This allows you to store state in a non-hackish way across invocations.
Upvotes: 6
Reputation: 1158
If I understand you correctly in you only need the literal first call to do thtp, you could make upgrade
a global variable. Then, when the download
function is called, you globally set it to False, and it will remain that way for subsequent calls.
Note that this answer is based on a certain reading of OP's question. I am assuming that the script calling this function does not know how many times the function has been called.
upgrade = True
def download():
global upgrade
if upgrade:
print('do a download using tftp')
upgrade = False
else:
print('do a download using http')
download() # do a download using tftp
download() # do a download using http
Upvotes: -1
Reputation: 44434
You can use a closure, that is, have an inner function which is returned, and this retains an outer state. This assumes python 3:
def init_download():
upgrade = True
def inner():
nonlocal upgrade
if upgrade:
print('do a download using tftp')
upgrade = False
else:
print('do a download via HTTP')
return inner
download = init_download()
download()
download()
download()
Gives:
do a download using tftp
do a download via HTTP
do a download via HTTP
Upvotes: 3
Reputation: 164843
Restructure your code as below:
def download(upgrade=True):
if upgrade:
do a download using tftp
else:
do a download via HTTP
In your second iteration, when you call download
, use upgrade=False
as a parameter:
download(False) # download via HTTP
Upvotes: 2