这是我参与更文挑战的第2天,活动详情查看: 更文挑战
前言
近来,项目上,遇见了用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
复制代码