Python 使用 'AND' 运算符的 While 循环
Python While Loop with 'AND' Operator
我不明白为什么下面的代码 return 设置了错误的值。
理想情况下,它应该 return 从今天开始的下一个星期二。相反,它 return 是今天的日期,'2021-08-17'
:
import datetime
def tue_the_fourth():
this_d = datetime.date.today()
if this_d.weekday() ==1 and this_d.day ==4:
return this_d.strftime("%Y-%m-%d")
else:
while (this_d.weekday() is not 1) and (this_d.day is not 4):
this_d=this_d + datetime.timedelta(days=1)
print(this_d)
return this_d.strftime("%Y-%m-%d")
我暂时忽略 is not
的错误使用,让我们关注核心问题:你的 while
测试 几乎总是错误的。当然,您的目标条件是错误的:
>>> (1 is not 1) and (4 is not 4)
False
想想看:
1 is not 1
为False,因为1等于1,所以和你测试相反
4 is not 4
为False,因为4等于4,所以也和你测试相反
但是,如果您在测试中更改了这些值中的 一个 ,您将 仍然 得到 False
:
1 is not 1
为假,
17 is not 4
为真,
但是如果 两个 测试都是真的,你的 while
只循环 运行s,因为你使用了 and
。由于今天是星期二,但日期是该月的 17 日,因此 while
循环不会 运行。在其他日子里,它会 运行 直到当前日期之后的第一个星期二,或者当它到达一个月的 4 号时,以先到者为准。
你想 运行 循环是 一个或另一个 是真的,所以你想在这里使用 or
,但见下文以获得更好的选择。
注意 correct test for integer inequality, is !=
,所以你想使用:
while this_d.weekday() != 1 or this_d.day != 4:
但这样说可能更容易:
while not (this_d.weekday() == 1 and this_d.day == 4):
您可能从 this_d.weekday() == 1 and this_d.day == 4
开始并试图反转该测试,但您不能仅将 not
添加到这些测试并让它通过。您掉进了经典的布尔反转陷阱并想了解 De Morgan's laws:
not (A or B) = (not A) and (not B)
not (A and B) = (not A) or (not B)
A and B
的倒数是 (not A) or (not B)
。但是,有时保持 not (A and B)
测试原样会更清楚。
进一步说明:
- 您不需要第一个
if
测试。当条件也满足时,循环不会运行,所以整个if
分支是多余的。
- 您可以使用
this_d += datetime.timedelta(days=1)
而不是 this_d = this_d + datetime.timedelta(days=1)
。查看增广赋值,这里更简单也更短。
- 我 return
date
对象。这将使您的函数在更多情况下可重用。有时您不需要立即格式化日期对象!
所以,我会写成:
def tue_the_fourth():
this_d = datetime.date.today()
while not (this_d.weekday() == 1 and this_d.day == 4):
this_d += datetime.timedelta(days=1)
return this_d
并且只有在必须将日期转换为字符串时才格式化日期,越晚越好。
如果我正确理解了您的目标,我会这样写:
def tue_the_fourth():
d = datetime.date.today()
while (d.weekday() != 1) or (d.day != 4):
d = d + datetime.timedelta(days=1)
print(d)
return d.strftime("%Y-%m-%d")
有什么变化,为什么?
使用 is not
作为逻辑 !=
是不好的做法并且不准确。
我将 while
更改为对条件执行逻辑 or
而不是 and
,基本上这是获得所需答案的方法。只要我们得到的一天是星期二或 4 号,而不是两者都是,使用答案就会停止。
整体清洁。不需要 if - else
语句,如果今天是 4 号星期二,则 while 不会 运行 一次,并且返回今天。
两期:
- 不要将原始值与
is
或 is not
进行比较,而是与 ==
或 !=
进行比较。
while
条件(错误)不是if
条件(正确)的否定
我还会更改算法,这样它就不会一次只执行一天,因为很明显第 4 天不是星期二,none 接下来的几天都是星期二月将是一场比赛。您不妨将日期加一个月,然后再试一次。
此外,您可以创建一个通用函数来查找某个月中的某一天,即某个工作日。
下面是这个想法的实现:
import datetime
def next_month(dt, day, month_count=1):
try:
return datetime.datetime(dt.year + int(dt.month + month_count > 12),
(dt.month + month_count - 1) % 12 + 1, day)
except ValueError: # invalid day in this month (like 30 February)
return next_month(dt, day, month_count+1)
def find_next(day, weekday):
this_d = datetime.date.today()
this_d = next_month(this_d, day, int(this_d.day > day))
while this_d.weekday() != weekday:
this_d = next_month(this_d, day)
return this_d.strftime("%Y-%m-%d")
# find next 4th on a Tuesday
print(find_next(4, 1)) # 2022-01-04 (when run on 2021-08-17)
我不明白为什么下面的代码 return 设置了错误的值。
理想情况下,它应该 return 从今天开始的下一个星期二。相反,它 return 是今天的日期,'2021-08-17'
:
import datetime
def tue_the_fourth():
this_d = datetime.date.today()
if this_d.weekday() ==1 and this_d.day ==4:
return this_d.strftime("%Y-%m-%d")
else:
while (this_d.weekday() is not 1) and (this_d.day is not 4):
this_d=this_d + datetime.timedelta(days=1)
print(this_d)
return this_d.strftime("%Y-%m-%d")
我暂时忽略 is not
的错误使用,让我们关注核心问题:你的 while
测试 几乎总是错误的。当然,您的目标条件是错误的:
>>> (1 is not 1) and (4 is not 4)
False
想想看:
1 is not 1
为False,因为1等于1,所以和你测试相反4 is not 4
为False,因为4等于4,所以也和你测试相反
但是,如果您在测试中更改了这些值中的 一个 ,您将 仍然 得到 False
:
1 is not 1
为假,17 is not 4
为真,
但是如果 两个 测试都是真的,你的 while
只循环 运行s,因为你使用了 and
。由于今天是星期二,但日期是该月的 17 日,因此 while
循环不会 运行。在其他日子里,它会 运行 直到当前日期之后的第一个星期二,或者当它到达一个月的 4 号时,以先到者为准。
你想 运行 循环是 一个或另一个 是真的,所以你想在这里使用 or
,但见下文以获得更好的选择。
注意 correct test for integer inequality, is !=
,所以你想使用:
while this_d.weekday() != 1 or this_d.day != 4:
但这样说可能更容易:
while not (this_d.weekday() == 1 and this_d.day == 4):
您可能从 this_d.weekday() == 1 and this_d.day == 4
开始并试图反转该测试,但您不能仅将 not
添加到这些测试并让它通过。您掉进了经典的布尔反转陷阱并想了解 De Morgan's laws:
not (A or B) = (not A) and (not B)
not (A and B) = (not A) or (not B)
A and B
的倒数是 (not A) or (not B)
。但是,有时保持 not (A and B)
测试原样会更清楚。
进一步说明:
- 您不需要第一个
if
测试。当条件也满足时,循环不会运行,所以整个if
分支是多余的。 - 您可以使用
this_d += datetime.timedelta(days=1)
而不是this_d = this_d + datetime.timedelta(days=1)
。查看增广赋值,这里更简单也更短。 - 我 return
date
对象。这将使您的函数在更多情况下可重用。有时您不需要立即格式化日期对象!
所以,我会写成:
def tue_the_fourth():
this_d = datetime.date.today()
while not (this_d.weekday() == 1 and this_d.day == 4):
this_d += datetime.timedelta(days=1)
return this_d
并且只有在必须将日期转换为字符串时才格式化日期,越晚越好。
如果我正确理解了您的目标,我会这样写:
def tue_the_fourth():
d = datetime.date.today()
while (d.weekday() != 1) or (d.day != 4):
d = d + datetime.timedelta(days=1)
print(d)
return d.strftime("%Y-%m-%d")
有什么变化,为什么?
使用
is not
作为逻辑!=
是不好的做法并且不准确。我将
while
更改为对条件执行逻辑or
而不是and
,基本上这是获得所需答案的方法。只要我们得到的一天是星期二或 4 号,而不是两者都是,使用答案就会停止。整体清洁。不需要
if - else
语句,如果今天是 4 号星期二,则 while 不会 运行 一次,并且返回今天。
两期:
- 不要将原始值与
is
或is not
进行比较,而是与==
或!=
进行比较。 while
条件(错误)不是if
条件(正确)的否定
我还会更改算法,这样它就不会一次只执行一天,因为很明显第 4 天不是星期二,none 接下来的几天都是星期二月将是一场比赛。您不妨将日期加一个月,然后再试一次。
此外,您可以创建一个通用函数来查找某个月中的某一天,即某个工作日。
下面是这个想法的实现:
import datetime
def next_month(dt, day, month_count=1):
try:
return datetime.datetime(dt.year + int(dt.month + month_count > 12),
(dt.month + month_count - 1) % 12 + 1, day)
except ValueError: # invalid day in this month (like 30 February)
return next_month(dt, day, month_count+1)
def find_next(day, weekday):
this_d = datetime.date.today()
this_d = next_month(this_d, day, int(this_d.day > day))
while this_d.weekday() != weekday:
this_d = next_month(this_d, day)
return this_d.strftime("%Y-%m-%d")
# find next 4th on a Tuesday
print(find_next(4, 1)) # 2022-01-04 (when run on 2021-08-17)