11

Now I got some problem that I can't explain and fix.
This is my first python module

TimeHelper.py

from datetime import datetime

def fun1(currentTime = datetime.now()):
    print(currentTime)

and another is

Main.py

from TimeHelper import fun1
import time

fun1()
time.sleep(5)
fun1()

When I run the Main.py, the out put is
2020-06-16 09:17:52.316714
2020-06-16 09:17:52.316714

My problem is why the time will be same in the result ? Is there any restrict when passing datetime.now() in to default parameter ?

EnergyBoy
  • 547
  • 1
  • 5
  • 18
  • 7
    Default parameters are only _evaluated once_. Duplicates exist, usually about lists or some such. – user2864740 Jun 16 '20 at 01:24
  • 1
    All the information of interest in https://stackoverflow.com/a/11416002/2864740 of https://stackoverflow.com/q/1132941/2864740 (note that the mutation works because the evaluation, of a new list, was only done _once_, not each call - same idea here, except backwards). Any answer here about the 'why' is a duplicate of the answer (first link), which includes relevant excerpt and reference. – user2864740 Jun 16 '20 at 01:25
  • 1
    One standard approach is then to default to `None`, and assign a value if the argument is `None` (eg. not specified). – user2864740 Jun 16 '20 at 01:27
  • Hi @user2864740 thanks for your reply, but now if I want to write a function that can accept 1 or 0 arg with type datetime, if age num is 1 and I can return the input datetime if 0 than return the current time(datetime.now()). how can I implement it ? – EnergyBoy Jun 16 '20 at 01:29
  • The third comment explains one approach (tldr: use `None` as the default, with an `if` of sorts). – user2864740 Jun 16 '20 at 01:29
  • 1
    thanks @user2864740 this comment help me! – EnergyBoy Jun 16 '20 at 01:34

3 Answers3

11

I think I find the answer. Thanks for @user2864740
So I change my TimeHelper.py to this

from datetime import datetime

def fun1(currentTime = None):
    if currentTime is None:
        currentTime = datetime.now()
    print(currentTime)

and anything work in my expectation.

EnergyBoy
  • 547
  • 1
  • 5
  • 18
  • 1
    Just a advice, When comparing object identity use `is` over `==` [see this](https://stackoverflow.com/questions/14247373/python-none-comparison-should-i-use-is-or) or you can simply do `if currentTime` and that will also work fine, see my answer . – Sarthak Kumar Jun 16 '20 at 01:50
  • @Sarthak thaks for your reply "is" operator works for me but "if currentTime" don't – EnergyBoy Jun 16 '20 at 01:53
  • 2
    Sorry my bad it would be `if not currentTime` as but using `is` is good practice. – Sarthak Kumar Jun 16 '20 at 02:00
5

It's because when you define a function datetime.now() is evaluated only at that time and that value is stored in currentTime, So whenever you run fun1 currentTime value does not update.
you can Simply do this in TimeHelper.py

from datetime import datetime

def fun1(currentTime=None):
    if currentTime:
        print(currentTime)
    else:
        print(datetime.now())

Hope it helps :)

Sarthak Kumar
  • 304
  • 5
  • 16
0

When assigning the variable in the function you actually assign it only once when you import the function. To assign it dynamically you need to set the variable inside the function every time it is ran.

from datetime import datetime

def fun1():
    currentTime = datetime.now()
    print(currentTime)

Edit:

If you want to specifically say what time then:

from datetime import datetime

def fun1(time):
    currentTime = time
    print(currentTime)
  • This will not allow the caller to specify a different time, which is the [only?] point of a default argument in the first place. – user2864740 Jun 16 '20 at 01:28
  • The edit requires a parameter, which negates the original desire to use a default value. See the question and main comments (some goals were clarified). – user2864740 Jun 16 '20 at 01:31
  • @user2864740 then the first aprroach is totally acceptable, you either set it or not. He did not want to have the same time each time. I gave two solutions what is the problem? – Dawid Wawrzynczyk Jun 16 '20 at 01:34
  • See the question and main comments. – user2864740 Jun 16 '20 at 01:35
  • @user2864740 I did, and I still don't get why make it more complicated that is should be? – Dawid Wawrzynczyk Jun 16 '20 at 01:36
  • "..now if I want to write a function that can accept 1 or 0 arg with type datetime, if age num is 1 and I can return the input datetime if 0 than return the current time(datetime.now()). how can I implement it?" - this was original goal of the question, hung-up with the behavior of default arguments. – user2864740 Jun 16 '20 at 01:47