运算子是一个非常常用的方法,因此在基础观念中也是绝对闪不了的。
最基本的运算子不外乎就是 +
(加)、-
(减)、*
(乘)、/
(除) 这几个运算子,而这几个运算子又称之为算数运算子,在 JavaScript 中的写法也不会与 Python 有太大的差异。
JavaScript:
console.log(1 + 1); // 2
console.log(2 * 2); // 4
console.log(8 - 2); // 6
console.log(16 / 2); // 8
Python:
print(1 + 1) # 2
print(2 * 2) # 4
print(8 - 2) # 6
print(16 / 2) # 8.0
而上面又称之为四则运算,但是唯独除法你可以看到 Python 是输出一个浮点数(float)。
疑?你注意到了吗?Python 的除法竟然输出一个浮点数
如果你写过 Python2 的人可能会更 WT...
所以这边先让我插入一个小片段说明一下 Python2 与 Python3 之间的差异。
这是一个比较特别的的地方,在原本的 Python2 的除法会是一个整数:
# Python2
print(16 / 2) # 8
虽然看起来没有什麽太大问题,但是如果你要做较精准的系统开发时,其实这就会有问题,因为 Python2 的除法会无条件舍去小数点,因此 Python2 的又称之为 floor division 或 integer division(整数除法?应该是这样翻,有错的话再跟我说一下)。
那就如同前面所言,如果我们要做比较精准处理时,就会有一些问题:
# Python2
print(16 / 3 == 16.0 / 3.0) # False
吓到了吗?如果没有吓到的话,我倒是吓到了,毕竟这两者应该是相同的才对,这个原因是因为 Python2 的除法运算子本身具有两种能力,也就是 Floating point division 与 integer division 的能力,只要你针对数字加上小数点就会被转换成浮点数除法。
那麽为了解决这个问题,Python3 之後将 /
运算子只保留 Floating point division 的能力也就是浮点数除法,所以在 Python3 结果就会变成以下:
# Python3
print(16 / 3) # 5.333333333333333
那麽因为这个修正的关系,我们在做较精准的计算上就可以比较安全:
# Python3
print(16 / 3 == 16.0 / 3.0) # True
如果你想更深入了解的话,建议你可以阅读这一篇 「PEP 238 -- Changing the Division Operator」官方文件。
好吧,这时候你应该会想说「如果我就是想要整数除法的话,该怎麽做呢?」
所以就让我们继续接着看下去吧~
由於 Python3 的修正关系,因此如果你依然想要做到整数除法的话,你可以使用 //
运算子:
print(16 // 3) # 5
虽然 //
运算子可以做到原本 Python2 类似的整数除法效果:
print(16 // 2) # 8
print(type(16 // 2)) # int
但是这边问题来了,你可以试着思考一下以下程序码结果为何:
print(100 / 3, type(100 / 3)) # ?, ?
print(100 // 3, type(100 // 3)) # ?, ?
print(100. // 3, type(100. // 3)) # ?, ?
紧张刺激了吗?让我们来看看结果吧!
print(100 / 3, type(100 / 3)) # 33.333333333333336, float
print(100 // 3, type(100 // 3)) # 33, int
print(100. // 3, type(100. // 3)) # 33.0, float
简单来讲 //
具备与 Python2 相同的能力,同时具有整数除法与浮点数除法的能力,所以在使用上就要多加小心。
这边也额外提一下关於加号运算子的部分,加号运算子其实满特别的。
为什麽这样讲呢?举例来讲如果你想把两个阵列合并的话在 JavaScript 中最简单的就是使用 concat()
函式:
var a = [1, 2, 3];
var b = [4, 5, 6];
var c = a.concat(b);
console.log(c); // [ 1, 2, 3, 4, 5, 6 ]
另一种比较进阶的作法则是使用 ES6 展开运算子:
var a = [1, 2, 3];
var b = [4, 5, 6];
var c = [...a, ...b];
console.log(c); // [ 1, 2, 3, 4, 5, 6 ]
如果你用加号运算子就会是另一种结果:
var a = [1, 2, 3];
var b = [4, 5, 6];
var c = a + b;
console.log(c); // "1,2,34,5,6"
至於原因的话,可以详见我先前写的 笔记 有提到此观念,所以这边就不多述了。
那麽 Python 呢?Python 就比较特别一点,Python 可以使用 加号运算子 快速达到这个阵列合并这个需求:
a = [1, 2 ,3]
b = [4, 5, 6]
c = a + b
print(c) # [1, 2, 3, 4, 5, 6]
超简单的对吧!
这边也简单提一下另一种合并阵列的方式,也就是前一章节所提到的 extend()
,但是这边要注意 extend()
会修改原有的阵列,因此并不会回传结果到新的变数上,这一点一定要注意一下:
a = [1, 2 ,3]
b = [4, 5, 6]
c = a.extend(b)
print(c) # None
print(a) # [1, 2, 3, 4, 5, 6]
最後这边还有另一种更简短加号运算子写法,但是它与 extend
的效果是一样的,它是修改原始的串列在赋予回去:
哦对了!Python 还有一些好玩的地方,例如你可以使用乘法运算子让字串加倍:
print('Ray' * 4) # RayRayRayRay
甚至是串列与元组的加倍也可以:
print(('https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/') * 4) # ('https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/', 'https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/', 'https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/', 'https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/')
# 元组
print(['https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/'] * 4) # ['https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/', 'https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/', 'https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/', 'https://www.facebook.com/HsiangFengWeb', 'https://hsiangfeng.github.io/']
那麽在四则运算中,其实还有一些比较进阶一点的用法,例如次方:
print(10 ** 2) # 100
print(12 ** 2) # 144
其他还有常见的运算子,例如:大於(>
)、小於(<
)、大於等於(>=
)、小於等於(<=
)等等,这边就只是列出四则运算多部份而已。
最後我想聊一个在 JavaScript 面试考题很常出现的问题,在 JavaScript 我们知道有所谓的优先性与相依性的观念,如果你不清楚的话,我会建议可以参考这一篇 JavaScript 核心观念(16)-运算子、型别与文法-优先性及相依性 文章。
那麽以 JavaScript 中很经典的题目就是 console.log(1 < 2 < 3); // true
但是反之若变成了 console.log(3 > 2 > 1); // false
结果就不同了。
所以这边也想探讨看看 Python 也会有这个问题吗?其实我们可以实际试试看:
print(1 < 2 < 3) # True
print(3 > 2 > 1) # True
可以看到结果都是 True
,这样代表 Python 没有优先性与相依性的问题吗?
其实是有的。
在 Python 文件 中有讲到这句话
请注意比较、成员检测和标识号检测均为相同优先级,并具有如 比较运算 一节所描述的从左至右串连特性。
因此你也可以在上面连结中看到底下这一张图,最上方优先性最高,最下方则是优先性最低:
所以前面的范例 print(3 > 2 > 1) # True
范例程序码它到底是怎麽运作的呢?
我们可以依照官方文件的解释来推敲一二:
例如 x < y <= z 等价于 x < y and y <= z,除了 y 只被求值一次(但在两种写法下当 x < y 值为假时 z 都不会被求值)。
透过上面的解释,我们可以得知范例程序码在运作的模式其实是 3 > 2
与 2 > 1
,这边要注意中间是 &
符号,代表着两边若有一边是 False
就会整个回传 False
,例如:
print(3 > 2 > 4) # False
如果用比较白话一点方式来看的话,结果就会像是 3 > 2 & 2 > 4
。
那我们今天运算子的章节就先到这边结束罗~
上网找到了一篇「绝对不会失败的溏心蛋」,结果实作之後还是失败了 Orz,实在太过不熟...但是不得不说有机鸡蛋的蛋腥味真的还好呢!
<<: 【在 iOS 开发路上的大小事-Day01】先装个 Xcode 开发环境压压惊
>>: Day 13 : 弱监督式标注资料 Snorkel (视觉关系侦测篇)
为了要让程序码更简洁、更容易懂、及更容易维护, 我们今天要开始将之前的测试程序重构,(虽然好像才刚开...
『导言』在 2019 年後,多媒体的搜寻流量在一些网站占比越来越高,现在可以说是经营网站的人都要去注...
通常分析 Event Correlation事件相关性,商业分析师 BA(Business Anal...
打开 Google Chrome, 首页就可以看到罗~ ...
如果画面太小或看不清楚,可移驾至 https://www.youtube.com/watch?v=...