说起来挺有意思的,编程这事儿吧,很多时候就是跟各种各样的数字打交道。奇数、偶数,这哥俩儿,简直是数字世界里最基础、最常客串的角色了。别看它简单,真到写代码解决问题的时候,你可能还真得琢磨琢磨:哎,我这手头的数据,python怎么偶数 才能把它准确无误地揪出来呢?或者说,我怎么让 Python 乖乖地给我生成一串偶数来用?今儿个,咱就来好好聊聊这个话题,不藏着掖着,把我在摸爬滚打中get到的那些招儿,都掰开揉碎了跟你说说。
最直接、最纯粹的“偶数判断”,其实就那么一招鲜,吃遍天。核心是什么?就是那个看着有点像百分号的运算符:%
。这货在 Python 里可不是算百分比的,它叫“取模运算符”。简单说,就是算除法剩下的那个零头。小学学除法都知道,一个数能被 2 整除,那它就是偶数,对吧?不能被 2 整除(也就是除以 2 还有余数),那就是奇数。Python 里的 % 2
干的正是这事儿。
比如,你想知道数字 10 是不是偶数,你就可以这么写:10 % 2
。Python 会告诉你结果是 0。为什么?因为 10 除以 2 商 5,余数是 0。那 7 呢?7 % 2
,结果是 1。商 3,余数 1。看明白了吧?一个数 num
,如果 num % 2 == 0
,没毛病,它就是个地地道道的偶数。如果 num % 2 != 0
(或者说 num % 2 == 1
,当然对于正数来说),那它就是个奇数。
所以,判断一个单独的数字是不是偶数,代码简单得让人想笑:
“`python
num = 10
if num % 2 == 0:
print(f”{num} 是偶数!”)
else:
print(f”{num} 是奇数!”)
another_num = 7
if another_num % 2 == 0:
print(f”{another_num} 是偶数!”)
else:
print(f”{another_num} 是奇数!”)
“`
运行一下,你会看到“10 是偶数!”和“7 是奇数!”。这招儿,甭管数字多大(只要 Python 的整数能装下,它可是“无限”大的!),都管用。
但咱们写代码,哪儿是光处理一个数啊,更多时候是面对一箩筐、一堆、一大串数字。比如,你拿到一个列表,里面混着奇数和偶数,老板说:“小王啊,把这列表里的偶数给我都挑出来,单独放一个新列表里!”这时候,光会判断单个数字就不够了,你得批量处理。
最直接的想法是什么?肯定是循环遍历呗!一个一个瞅过去,是偶数的,就把它捞出来,放到咱们准备好的新篮子里。
“`python
my_numbers = [1, 5, 8, 12, 17, 20, 23, 30, 45, 50]
even_numbers = [] # 准备一个空篮子
odd_numbers = [] # 再来个放奇数的篮子,顺便也处理了
for number in my_numbers:
if number % 2 == 0: # 判断是不是偶数
even_numbers.append(number) # 是偶数就放偶数篮子
else:
odd_numbers.append(number) # 不是偶数(就是奇数)就放奇数篮子
print(“原始列表:”, my_numbers)
print(“捞出来的偶数:”, even_numbers)
print(“剩下的奇数:”, odd_numbers)
“`
这段代码跑起来,even_numbers
里就会是 [8, 12, 20, 30, 50]
。逻辑清晰,一步一步来,没毛病。这方法好理解,写起来也直观,对于新手来说,用 for
循环加 if
判断,绝对是入门的好姿势。
不过呢,写 Python 写久了,人总会追求那么一点点“优雅”,一点点“简洁”。当你发现一个操作可以用一行代码漂亮地搞定,那种感觉,怎么说呢,就像找到了武林秘籍一样!对于从列表中筛选出偶数这种事儿,Python 就提供了这么一个大杀器——列表推导式(List Comprehensions)。
还记得上面那个 for
循环吗?它干的事儿是:遍历 my_numbers
里的每一个 number
,如果 number % 2 == 0
条件成立,就把这个 number
收集起来。列表推导式就是把这个过程压缩到了一行里,而且读起来感觉更像是英语句子。
“`python
my_numbers = [1, 5, 8, 12, 17, 20, 23, 30, 45, 50]
用列表推导式筛选偶数
even_numbers_comprehension = [number for number in my_numbers if number % 2 == 0]
print(“用列表推导式捞出来的偶数:”, even_numbers_comprehension)
“`
这一行 [number for number in my_numbers if number % 2 == 0]
,是不是看着就清爽很多?它的意思就是:“创建一个新的列表,列表里的元素是 number
,这个 number
来自 my_numbers
里面的每一个 number
,但前提是 number
必须满足 number % 2 == 0
这个条件。” 简直是把之前的 for
循环加 if
判断给“翻译”成了更 Pythonic 的表达方式。对于这种基于现有序列进行过滤或转换生成新序列的场景,列表推导式简直是绝配!当然,过滤奇数也一样简单,把条件改成 if number % 2 != 0
就好了。
除了从现有数字里挑,有时候咱们还需要“平地起高楼”,直接生成一串连续的偶数。比如,需要 1 到 100 之间的所有偶数。这时候,Python 的 range()
函数就派上用场了。range()
通常用来生成一个整数序列,但它有个特别方便的地方,就是可以指定步长(step)。默认步长是 1,也就是一个一个跳。但如果你把步长设成 2 呢?它就可以实现隔一个跳一个!
要生成从某个偶数开始、到某个偶数结束(或接近结束)的偶数序列,可以这样做:
“`python
生成 2 到 10 之间的偶数 (不包含 11)
even_sequence_1 = list(range(2, 11, 2))
print(“用 range(2, 11, 2) 生成的偶数:”, even_sequence_1) # 结果是 [2, 4, 6, 8, 10]
生成 1 到 100 之间的偶数
注意 range 的结束点是“开区间”,不包含结束值
如果要包含 100,结束值需要设为 101
even_sequence_2 = list(range(2, 101, 2))
print(“用 range(2, 101, 2) 生成的偶数:”, even_sequence_2) # 结果是 [2, 4, 6, …, 100]
“`
这里 range(start, stop, step)
的意思是:从 start
开始(包含 start
),每次增加 step
,直到达到或超过 stop
(不包含 stop
)。所以 range(2, 101, 2)
就是从 2 开始,每次跳 2,得到 2, 4, 6, … 直到 100,因为下一个是 102 超过了 101。
当然,你也可以先用 range
生成所有数字,再用列表推导式去过滤。比如 [num for num in range(1, 101) if num % 2 == 0]
。这两种方式都能得到 1 到 100 的偶数。选择哪种?用 range(start, stop, step)
直接生成偶数更有效率,因为它一开始就只生成偶数;而先生成所有数字再过滤,会生成更多的中间结果。不过,对于不太大的范围,这点效率差别倒也无伤大雅,看你觉得哪种写法更顺眼吧。
有时候,我们不光处理正偶数,零和负偶数也可能遇到。数学上,0 是偶数,负偶数(比如 -2, -4)也是偶数。Python 的 %
运算符在这方面表现得很“数学”。
python
print(f"0 % 2 的结果是: {0 % 2}") # 结果是 0
print(f"-4 % 2 的结果是: {-4 % 2}") # 结果是 0
print(f"-3 % 2 的结果是: {-3 % 2}") # 结果是 1 (或 -1,Python 3 的 % 结果与除数符号一致,但对于 % 2,余数非 0 即 1 或 -1,== 0 的判断是准确的)
你看,0 和 -4 除以 2 的余数都是 0,所以 num % 2 == 0
这个判断对零和负偶数依然有效。这省去了单独处理零和负数的情况,挺省心的。
话说回来,为啥要揪着偶数不放呢?哎呀,这用处可多了去了!比如,你处理表格数据,可能需要隔行进行某种操作(比如高亮),行号是偶数或者奇数就成了判断条件。写游戏呢?可能角色的某些行为只在偶数回合发生。处理图片?像素坐标里,偶数坐标和奇数坐标可能有不同的意义。或者,你写个小工具,需要用户输入一个数字,然后告诉你这个数字是不是“幸运偶数”(随便编的),那第一步不就得判断它是不是偶数嘛。
再扯远一点点,除了 % 2 == 0
这种直观的方法,有没有更“底层”或者说更Geek一点的判断偶数的方法?有!那就是位运算。我们知道,计算机底层存数字是用二进制。一个整数是偶数还是奇数,看它二进制的最后一位(最低位)就行了。如果是 0,那就是偶数;如果是 1,那就是奇数。
位运算里的“按位与”运算符 &
,可以用来检查某一位是不是 0 或 1。把一个数和 1 进行“按位与”操作,结果就是这个数二进制表示的最低位。为啥是和 1?因为 1 的二进制表示是 ...0001
,只有最低位是 1,其他位都是 0。任何数跟一个所有位都是 0 的数进行按位与,结果都是 0。所以 num & 1
的结果,就取决于 num
的最低位:如果 num
的最低位是 0,结果就是 ...0000 & ...0001 = ...0000
,也就是 0。如果 num
的最低位是 1,结果就是 ...xxxx1 & ...0001 = ...0001
,也就是 1。
所以,判断偶数,也可以写成 num & 1 == 0
:
“`python
num1 = 10 # 二进制是 …1010
num2 = 7 # 二进制是 …0111
print(f”{num1} & 1 的结果是: {num1 & 1}”) # 结果是 0
print(f”{num2} & 1 的结果是: {num2 & 1}”) # 结果是 1
if num1 & 1 == 0:
print(f”{num1} 用位运算判断是偶数”)
if num2 & 1 != 0: # 或者 num2 & 1 == 1
print(f”{num2} 用位运算判断是奇数”)
“`
这种位运算的方法,在某些场景下(比如追求极致性能,或者在一些对位操作友好的语言里),可能比取模运算更快一点点。但在 Python 里,% 2 == 0
通常已经足够快,而且可读性甩位运算好几条街。毕竟不是每个人都对二进制位运算那么熟悉,写代码,能让人一眼看懂也很重要。个人感觉,对于日常编程,% 2 == 0
是最通用、最推荐的判断偶数姿势。位运算嘛,知道有这么回事儿就行,真要用得谨慎点,加点注释啥的,别把后来看你代码的人(或者未来的自己)给绕晕了。
最后,再强调一遍。在 Python 里处理偶数,无论是判断一个数、从一堆数里筛选,还是生成一串数,核心概念都离不开“能被 2 整除余数为 0”这个数学定义。而实现这个定义,最常用的工具就是取模运算符 %
。围绕着它,咱们学会了简单的 if
判断,批量处理的 for
循环,更优雅的列表推导式,以及生成序列的 range()
函数。甚至还看了眼有点“黑科技”的位运算。
学编程就像学门手艺,工具箱里的工具越多越好,但更重要的是知道在什么场景下掏哪个工具出来最合适。判断偶数这事儿,看起来小,里面门道也不少呢。多练多试,你自然就能找到最顺手、最高效的 python怎么偶数 处理方式了。去试试吧!
评论(0)