前言
近来,项目上,遇见了用Python编写的发布脚本,瞬间就被她迷人的眼神和身段迷上了。近来几天一直追随她,越发的喜爱。喜爱之余,拿她与我的前任(JS)最了一些对比。 当然纯语法的对比,那太单调。这里我就实现一些基本的功能来对比两者语法上的一些差异。
源码都放在github上面了: Python PK JS
新欢(Python) VS 前任(JS)
字符串截取
Python一点都不废话,直接[:]
搞定。
Python
text = "你们都是坏人啊" print(text[0:5]) # 你们都是坏 复制代码
JS
const print = console.log const text = "你们都是坏人啊" print(text.substring(0,5)) // 你们都是坏 复制代码
时间格式化
很明显,在没有借助第三方库的前提下,JS格式化时间的能力还是比较弱的。当然有些人会说,JS的 Date.prototype.toLocaleString
能做到一定的格式化,但毕竟能力有限。
还有字符串的填充问题,1月应该显示为 01
。 而这种能力居然在Python时间格式化函数里面是现成的。
import time def format(date): return time.strftime("%Y-%m-%d %H:%M:%S", date) print(format((2020, 1, 1, 1, 1, 1, 0, 0, 0))) # 2020-01-01 01:01:01 复制代码
function padNum(num, length = 2, ch = "0") { return `${num}`.padStart(length, ch); } function formatDate(date) { const d = new Date(date); const fullYear = d.getFullYear(); const month = padNum(d.getMonth() + 1) const day = padNum(d.getDate()) const h = padNum(d.getHours()) const m = padNum(d.getMinutes()) const s = padNum(d.getSeconds()) return `${fullYear}-${month}-${day} ${h}:${m}:${s}` } console.log(formatDate(new Date(2020, 0, 1, 1, 1, 1))); // 2020-01-01 01:01:01 复制代码
对象属性设置和遍历
Python把JS里面的对象叫做字典。
采用类似对象字面量形式申明的时候,属性名还必须是类似JSON的形式,必须以"
包起来。
设置值的时候不能像JS那样 obj.name
,而必须是obj["name"]
遍历自身属性的时候,比JS方便一些,而不用借助外力。
Python
obj = { "name": "Tom", "age": 10, "weight": 60, "height": 100 } obj["name"] = "Tom +" obj["age"] = 100 print(obj) # 输出所有的属性键 print("keys:", obj.keys()) print() print("----------------------") for k in obj.keys(): print("key:", k, " value:", obj[k]) 复制代码
const print = console.log const obj = { name: "Tom", age: 10, weight: 60, height: 100 } obj.name = "Tom +"; obj["age"] = 100; print(obj); // 输出所有的属性键 print("keys:", Object.keys(obj)) for(let k in obj){ print("key:", k, " value:", obj[k]) } 复制代码
正则替换和分组
Python中的正则替换使用的是re.sub
,二这个能力在js里面是字符串自带的能力。虽然Python里面的字符串也有replace
方法,是纯字符串的替换。
至于分组,Python这边的体验好太多了。
import re # 替换#后面的内容为空 text = "158000000#手机号码"; print(re.sub("#.*$","", text)); #158000000 # 分组 dateText = "2018-01-06"; reDate = re.compile("(\d{4})-(\d{1,2})-(\d{1,2})"); print(reDate.search(dateText).groups()) # ('2018', '01', '06') 复制代码
const print = console.log; // 替换#后面的内容为空 const text = "158000000#手机号码"; print(text.replace(/#.*$/,"")); //158000000 // 分组 dateText = "2018-01-06"; execArray = /(\d{4})-(\d{1,2})-(\d{1,2})/.exec(dateText) print(execArray) // ['2018-01-06','2018','01','06',index: 0,input: '2018-01-06', groups: undefined ] // /(\d{4})-(\d{1,2})-(\d{1,2})/.exec(dateText) // print(":", RegExp.$1, RegExp.$2, RegExp.$3) 复制代码
数组
数组增加,删除,查找
Python里面对应的是list.
Python整体的语法还是相对简单一点,尤其是可以直接根据某个值删除。 JS里面的数组内置的方法更加的多,功能也相对强大一些。 Python有一个单独的array模块来增强。
arr = ["1", 2, "1", "3"]; # 尾部增加 arr.append(10000); print(arr); # ['1', 2, '1', '3', 10000] # 头部增加 arr.insert(0, -10000); print(arr); # [-10000, '1', 2, '1', '3', 10000] # 查找值的位置 index = arr.index(10000); print("index", index) # index 5 # 修改 arr[2] = 3; print(arr); # [-10000, '1', 3, '1', '3', 10000] # 删除 arr.remove("1") print(arr); # [-10000, 3, '1', '3', 10000] # 删除 arr.remove("1") print(arr); # [-10000, 3, '3', 10000] 复制代码
const print = console.log const arr = ["1", 2, "1", "3"]; // 尾部增加 arr.push(10000); print(arr); // [ '1', 2, '1', '3', 10000 ] // 头部增加 arr.unshift(-10000) print(arr); // [ -10000, '1', 2, '1', '3', 10000 ] // 查找值的位置 let index = arr.indexOf(10000) print("index", index) // index 5 // 修改 arr[2] = 3; print(arr); // [ -10000, '1', 3, '1', '3', 10000 ] // 删除 index = arr.indexOf("1"); arr.splice(index, 1) print(arr); // [ -10000, 3, '1', '3', 10000 ] // 删除 index = arr.indexOf("1"); arr.splice(index, 1) print(arr); // [ -10000, 3, '3', 10000 ] 复制代码
数组填充
Python自带的range这里就很亮眼。
还有这酷酷的 推导式[m for m in range(1, 101, 1)]
# arr = list(range(1, 101, 1)); arr = [m for m in range(1, 101, 1)] print(arr) # [1,2,3 ......, 100] 复制代码
const print = console.log; const arr = Array.from({ length: 100 }, (v, i) => { return i + 1 }); print(arr); // [1,2,3 ......, 100] 复制代码
遍历文件夹和获取所有文件
遍历文件夹
Python是两层for循环,但是非常直接。 JS这边是传统的递归。
import os import sys def walk(dir): for root, dirs, files in os.walk(dir): for file in files: print(os.path.join(root, file)) for dir in dirs: print(os.path.join(root, dir)) currentDir = os.path.split(os.path.realpath(sys.argv[0]))[0] walk(currentDir); 复制代码
const path = require("path"); const fs = require("fs"); function walk(root) { const dirs = fs.readdirSync(root); dirs.forEach(dir => { const fullPath = path.join(root, dir); const sta = fs.statSync(fullPath); if(sta.isFile()){ return console.log(fullPath); } console.log(fullPath); walk(fullPath); }); } walk(__dirname); 复制代码
获取文件夹全部文件路径
哇,采用内置的glob
一气呵成。
其实nodejs也是有相关模块的 glob,不过那是第三方的库了。
import os import glob import sys def getFiles(dir): return glob.glob("%s/**/*.*" % (dir), recursive=True) currentDir = os.path.split(os.path.realpath(sys.argv[0]))[0] print("currentDir", currentDir) files = getFiles(currentDir) print(files) 复制代码
const path = require("path"); const fs = require("fs"); function getFiles(root, files) { const dirs = fs.readdirSync(root); dirs.forEach(dir => { const fullPath = path.join(root, dir); const sta = fs.statSync(fullPath); if(sta.isFile()){ return files.push(fullPath); } getFiles(fullPath, files); }); return files; } const files = []; getFiles(__dirname, files); console.log(files); 复制代码
网络请求
下面发送https请求获取百度首页的内容, Python使用内置库并不轻松。
如果发送的是http请求,Python会简单很多。
这里我发现一个很有意思的问题,Python和NodeJS发送的是get请求,但是返回的结果却不同。 有哪位要是知道原因和更多细节,麻烦请帮忙解惑。
import urllib.request import urllib.parse import os import sys import ssl currentDir = os.path.split(os.path.realpath(sys.argv[0]))[0]; headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36", } context = ssl._create_unverified_context() request = urllib.request.Request('https://www.baidu.com', headers=headers) res = urllib.request.urlopen(request, context=context) html = res.read().decode('utf-8') with open(os.path.join(currentDir, "./_py_baidu.html"), mode="w", encoding="utf-8") as f: f.write(html) 复制代码
const https = require('https'); const fs = require("fs"); const path = require("path"); https.get('https://www.baidu.com', (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { console.log("data", data); fs.writeFileSync(path.join(__dirname, "./_js_baidu.html"), data); }); }).on("error", (err) => { console.log("Error: " + err.message); }); 复制代码
随机数
Python内置的random
相当的强大。
JS其实也可以借助三角函数等来随机生成,爽感当然差一些。 虽然可以借助第三方random。
import random # 0-1随机数 print(random.random()) # 1-10随机整数 print(random.randint(1, 10)) # 随机偶数 print(random.randrange(0, 1000, 2)) # 随机浮点数 print(random.uniform(0.1, 3.6)) # 权重相等,选择3个 print(random.choices([1, 2, 3, 4, 5], [1, 1, 1, 1, 1], cum_weights=None, k=3)) 复制代码
const print = console.log; function randInt(min, max) { return Math.floor(Math.random() * (max - min)) + min } function rand(min, max) { return Math.random() * (max - min) + min; } // 0-1之间随机数 print(Math.random()) // 1-10之间随机整数 print(randInt(1, 10)) // 0-1000之间 随机偶数 let num = randInt(0, 1000); num = num % 2 === 0? num : num -1; print(num) // // 随机浮点数 print(rand(0.1, 3.6)) // 权重相等,选择3个 // 难搞。。。。。 复制代码
异常捕获
Python的异常捕获更直接和好懂一些, 而JS得额外通过错误的类型判断,再进行进一步的处理。
Python也是可以通过isinstance
来进一步处理的。
try: raise TypeError("类型错误"); open(".../xxxxxx.ts") except IOError as ioe: print("io error", ioe) except TypeError as te: print("type error", te); except Exception as e: print("common error", e.args) finally: print("执行完毕") 复制代码
const fs = require("fs"); const print = console.log; try { throw new TypeError("无效的类型") fs.openSync("../sdasdas/x.ts") } catch (err) { if (err instanceof TypeError) { print("type error", err) } else if (err instanceof Error) { print("common error", err) } } 复制代码
类继承
JS的类继承,更加容易理解。和Java, C#等无太大区别。
Python的类,都是带着self奔跑的, 构造函数是 __init__
。每个方法第一个参数也是self
。
class Animal(): def __init__(self, sex): self.sex = sex; def eat(self): print("eat"); def getSex(self): print("sex", self.sex) class Human(Animal): def __init__(self, sex): super().__init__(sex) def walk(self): print("walk") human = Human(1); human.getSex(); human.eat(); human.walk(); 复制代码
const print = console.log class Animal { constructor(sex) { this.sex = sex; } getSex() { print("sex", this.sex); } eat() { print("eat") } } class Human extends Animal { constructor(sex) { super(sex) } walk() { print("walk"); } } var human = new Human(1, 0); human.getSex(); human.eat(); human.walk(); 复制代码
其他有趣的
print(1 == "1") # False print([1] + [2]) # [1,2] print([1, 2, 3] == [1, 2, 3]) # True print(3 > 2 > 1) # True 复制代码
const print = console.log; print(1 == "1") // true print([1] + [2]) // 12 print([1, 2, 3] == [1, 2, 3]) // false print(3 > 2 > 1); // false 复制代码