Python 和 JS 有哪些相同之处

【嵌牛导读】Python 是一门运用很广泛的语言,自动化脚本、爬虫,甚至在深度学习领域也都有 Python 的身影。作为一名前端开发者,也了解 ES6 中的很多特性借鉴自 Python (比如默认参数、解构赋值、Decorator等),同时本文会对 Python 的一些用法与 JS 进行类比。不管是提升自己的知识广度,还是更好地迎接 AI 时代,Python 都是一门值得学习的语言。

【嵌牛鼻子】python与JS的相似之处

【嵌牛提问】python与JS有哪些相似呢?

【嵌牛正文】

数据类型

在 Python 中,最常用的能够直接处理的数据类型有以下几种:

数字[整数(int)、浮点型(float)、长整型(long)、复数(complex)]

字符串(str)

布尔值(bool)

空值(None)

除此之外,Python 还提供了列表[list]、字典[dict] 等多种数据类型,这在下文中会介绍。

类型转换与类型判断

与 JS 十分类似,python 也能实现不同数据类型间的强制与隐式转换,例子如下:

强制类型转换:

int('3') # 3
str(3.14) # '3.14'
float('3.14') # 3.14
# 区别于 JS 只有 Number 一种类型,Python 中数字中的不同类型也能相互强制转换
float(3) # 3.0
bool(3) # True
bool(0) # False

隐式类型转换:

1 + 1.0 # 2.0
1 + False # 1
1.0 + True # 2.0
# 区别于 JS 的 String + Number = String, py 中 str + int 会报错
1 + '1' # TypeError: cannot concatenate 'str' and 'int' objects

此外写代码的时候经常会需要判断值的类型,可以 使用 python 提供的 type() 函数获取变量的类型,或者使用 isinstance(x, type) 来判断 x 是否属于相应的 type 类型。

type(1.3) == float # True
isinstance('a', str) # True
isinstance(1.3, int) # False
isinstance(True, bool) # True
isinstance([], list) # True
isinstance({}, dict) # True

有序集合类型

集合是指包含一组元素的数据结构,有序集合即集合里面的元素是是按照顺序排列的,Python 中的有序集合大概有以下几类:list, tuple, str, unicode。

list 类型

Python 中 List 类型类似于 JS 中的 Array,

L = [1, 2, 3]
print L[-1] # '3'
L.append(4) # 末尾添加元素
print L # [1, 2, 3, 4]
L.insert(0, 'hi') # 指定索引位置添加元素
print L # ['hi', 1, 2, 3, 4]
L.pop() # 末尾移除元素 L.pop(2) ?????? 2 ???
print L # ['hi', 1, 2, 3]

tuple 类型

tuple 类型是另一种有序的列表,中文翻译为" 元组 "。tuple 和 list 非常类似,但是,tuple 一旦创建完毕,就不能修改了。

t = (1, 2, 3)
print t[0] # 1
t[0] = 11 # TypeError: 'tuple' object does not support item assignment
t = (1)
print t # 1 t 的结果是整数 1
t = (1,) # 为了避免出现如上有歧义的单元素 tuple,所以 Python 规定,单元素 tuple 要多加一个逗号","
print t # (1,)

无序集合类型

dict 类型

Python 中的 dict 类型类似于 JS 中的 {} (最大的不同是它是没有顺序的), 它有如下特点:

查找速度快 (无论 dict 有 10 个元素还是 10 万个元素,查找速度都一样)

占用内存大 (与 list 类型相反)

dict 中的 key 不能重复

dict 中存储的 key-value 序对是没有顺序的

d = {
  'a': 1,
  'b': 2,
  'c': 3
}

print d # {'a': 1, 'c': 3, 'b': 2}  可以看出打印出的序对没有按正常的顺序打出

# 遍历 dict
for key,value in d.items():
  print('%s: %s' % (key,value))
# a: 1
# c: 3
# b: 2

set 类型

有的时候,我们只想要 dict 的 key,不关心 key 对应的 value,而且要保证这个集合的元素不会重复,这时,set 类型就派上用场了。set 类型有如下特点:

set 存储的元素和 dict 的 key 类似,必须是不变对象

set 存储的元素也是没有顺序的

s = set(['A', 'B', 'C', 'C'])
print s # set(['A', 'C', 'B'])
s.add('D')
print s # set(['A', 'C', 'B', 'D'])
s.remove('D')
print s # set(['A', 'C', 'B'])

Python 中的迭代

在介绍完 Python 中的有序集合和无序集合类型后,必然存在遍历集合的 for 循环。但是和其它语言的标准 for 循环不同,Python 中的所有迭代是通过 for ... in 来完成的。以下给出一些常用的迭代 demos:

索引迭代:

L = ['apple', 'banana', 'orange']
for index, name in enumerate(L): # enumerate() 函数把 ['apple', 'banana', 'orange'] 变成了类似 [(0, 'apple), (1, 'banana'), (2, 'orange')] 的形式
  print index, '-', name
# 0 - apple
# 1 - banana
# 2 - orange

迭代 dict 的 value:

d = { 'apple': 6, 'banana': 8, 'orange': 5 }
print d.values() # [6, 8, 5]
for v in d.values()
  print v
# 6
# 8
# 5

迭代 dict 的 key 和 value:

d = { 'apple': 6, 'banana': 8, 'orange': 5 }
for key, value in d.items()
  print key, ':', value
# apple : 6
# banana: 8
# orange: 5

切片操作符

Python 提供的切片操作符类似于 JS 提供的原生函数 slice()。有了切片操作符,大大简化了一些原来得用循环的操作。

L = ['apple', 'banana', 'orange', 'pear']
L[0:2] # ['apple', 'banana'] 取前 2 个元素
L[:2] # ['apple', 'banana'] 如果第一个索引是 0,可以省略
L[:] # ['apple', 'banana', 'orange', 'pear'] 只用一个 : ,表示从头到尾
L[::2] # ['apple', 'orange'] 第三个参数表示每 N 个取一个,这里表示从头开始,每 2 个元素取出一个来

列表生成器

如果要生成 [1x1, 2x2, 3x3, ..., 10x10] 怎么做?方法一是循环:

L = []
for x in range(1, 11):
  L.append(x * x)

但是循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的 list:

# 把要生成的元素 x * x 放到前面,后面跟 for 循环,就可以把 list 创建出来

[x * x for x in range(1, 11)]

# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

列表生成式的 for 循环后面还可以加上 if 判断(类似于 JS 中的 filter() 函数),示例如下:

[x * x for x in range(1, 11) if x % 2 == 0]

# [4, 16, 36, 64, 100]

for 循环可以嵌套,因此,在列表生成式中,也可以用多层 for 循环来生成列表。

[m + n for m in 'ABC' for n in '123']
# ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

Python 函数

默认参数

JS 中 ES6 的 默认参数正是借鉴于 Python,用法如下:

def greet(name='World'):
  print 'Hello, ' + name + '.'
greet() # Hello, World.
greet('Python') # Hello, Python.

可变参数

类似于 JS 函数中自动识别传入参数的个数,Python 也提供了定义可变参数,即在可变参数的名字前面带上个 * 号。

def fn(*args):
  print args
fn() # ()
fn('a') # ('a',)
fn('a', 'b') # ('a', 'b')

Python 解释器会把传入的一组参数组装成一个 tuple 传递给可变参数,因此,在函数内部,直接把变量 args 看成一个 tuple 就好了。

常用高阶函数

Python 中常用的函数 (map、reduce、filter) 的作用和 JS 中一致,只是用法稍微不同。

map 函数: 接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。

def f(x):
  return x * x
print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # [1, 4, 9, 16, 25, 36, 49, 64, 81]

reduce 函数: 接收一个函数 f 和一个 list(可以接受第三个值作为初始值),reduce() 对 list 的每个元素反复调用函数 f,并返回最终结果值。

def f(x, y):
  return x * y
reduce(f, [1, 3, 5]) # 15

filter 函数: 接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter() 根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新 list。

def is_odd(x):
  return x % 2 == 1
filter(is_odd, [1, 4, 6, 7, 9, 12, 17]) # [1, 7, 9, 17]

匿名函数

和 JS 的匿名函数不同的地方是,Python 的匿名函数中只能有一个表达式,且不能写 return。拿 map() 函数为例:

map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # [1, 4, 9, 16, 25, 36, 49, 64, 81]

关键词 lambda 表示匿名函数,冒号前面的 x 表示函数参数,可以看出匿名函数 lambda x: x* x实际上就是:

def f(x):
  return x * x

闭包

之前写过一些关于 JS 闭包的文章,比如 深入浅出JavaScript之闭包(Closure)、以及 读书笔记-你不知道的 JavaScript (上),Python 中闭包的定义和 JS 中的是一致的即:内层函数引用了外层函数的变量,然后返回内层函数。下面来看下 Py 中闭包之 for 循环经典问题:

# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
  fs = []
  for i in range(1, 4):
    def f():
      return i * i
    fs.append(f)
  return fs
f1, f2, f3 = count() # 这种写法相当于 ES6 中的解构赋值
print f1(), f2(), f3() # 9 9 9

老问题了,f1(), f2(), f3() 结果不应该是 1, 4, 9 吗,实际结果为什么都是 9 呢?

原因就是当 count() 函数返回了 3 个函数时,这 3 个函数所引用的变量 i 的值已经变成了 3。由于 f1、f2、f3 并没有被调用,所以,此时他们并未计算 i*i,当 f1 被调用时,i 已经变为 3 了。

要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。代码修改如下:

方法一: 可以理解为创建了一个封闭的作用域,i 的 值传给 j 之后,就和 i 没任何关系了。每次循环形成的闭包都存进了内存中。

def count():
  fs = []
  for i in range(1, 4):
    def f(j):
      def g(): # 方法一
        return j * j
      return g
    r = f(i)
    fs.append(r)
  return fs
f1, f2, f3 = count()
print f1(), f2(), f3() # 1 4 9

方法二:思路比较巧妙,用到了默认参数 j 在函数定义时可以获取到 i 的值,虽然没有用到闭包,但是和方法一有异曲同工之处。

def count():
  fs = []
  for i in range(1, 4):
    def f(j = i): # 方法二
      return j * j
    fs.append(f)
  return fs
f1, f2, f3 = count()
print f1(), f2(), f3() # 1 4 9

decorator 装饰器

ES6 的语法中的 decorator 正是借鉴了 Python 的 decorator。decorator 本质上就是 一个高阶函数,它接收一个函数作为参数,然后返回一个新函数。

那装饰器的作用在哪呢?先上一段日常项目中用 ts 写的网关代码:

@Post('/rider/detail') // URL 路由
@log()         // 打印日志
 @ResponseBody
 public async getRiderBasicInfo(
  @RequestBody('riderId') riderId: number,
  @RequestBody('cityId') cityId: number,
 ) {
  const result = await this.riderManager.findDetail(cityId, riderId)
  return result
 }

可以看出使用装饰器可以极大地简化代码,避免每个函数(比如日志、路由、性能检测)编写重复性代码。

回到 Python 上,Python 提供的 @ 语法来使用 decorator, @ 等价于 f = decorate(f)。下面来看看 @log() 在 Python 中的实现:

# 我们想把调用的函数名字给打印出来
@log()
def factorial(n):
  return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
# 来看看 @log() 的定义
def log():
  def log_decorator(f):
    def fn(x):
      print '调用了函数' + f.__name__ + '()'
      return f(x)
    return fn
  return log_decorator
# 结果
# 调用了函数 factorial()
# 3628800
class

面向对象编程

面向对象编程是一种程序设计范式,基本思想是:用类定义抽象类型,然后根据类的定义创建出实例。在掌握其它语言的基础上,还是比较容易理解这块知识点的,比如从下面两种写法可以看出不同语言的语言特性间竟然有如此多的共性。

es6: (附:本文的主题是 python,所以只是初略展示下 js 中类的定义以及实例的创建,为了说明写法的相似性)

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
}
const child1 = new Person('Xiao Ming', 10)

Python: (核心要点写在注释中)

# 定义一个 Person 类:根据 Person 类就可以造成很多 child 实例
class Person(object):
  address = 'Earth' # 类属性 (实例公有)
  def __init__(self, name, age): # 创建实例时,__init__()方法被自动调用
    self.name = name
    self.age = age
  def get_age(self): # 定义实例方法,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和普通函数是一样的
    return self.age
child1 = Person('Xiao Ming', 10)
child2 = Person('Xiao Hong', 9)
print child1.name # 'Xiao Ming'
print child2.get_age() # 9
print child1.address # 'Earth'
print child2.address # 'Earth'

继承

child 属于 Student 类,Student 类属于 People 类,这就引出了继承: 即获得了父类的方法属性后又能添加自己的方法属性。

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
class Student(Person):
  def __init__(self, name, age, grade):
    super(Student, self).__init__(name, age) # 这里也能写出 Person.__init__(self, name, age)
    self.grade = grade
s = Student('Xiao Ming', 10, 90)
print s.name # 'Xiao Ming'
print s.grade # 90

可以看到子类在父类的基础上又增加了 grade 属性。我们可以再来看看 s 的类型。

isinstance(s, Person)
isinstance(s, Student)

可以看出,Python 中在一条继承链上,一个实例可以看成它本身的类型,也可以看成它父类的类型。

总结

以上所述是小编给大家介绍的Python 和 JS 有哪些相同之处,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • python读写json文件的简单实现

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C.C++.Java.JavaScript.Perl.Python等).这些特性使JSON成为理想的数据交换语言.易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率). JSON在python中分别由list和dict组成. 这是用于序列化的两个模块: json: 用于

  • python中字符串类型json操作的注意事项

    python操作json的方法有 json.dumps--将json对象(字典)转换为字符串对象 json.loads--将字符串对象转换为json对象(字典) 如果定义json对象 jsonstring1={"results":[{"id":"1","name":"\u9ed8\u8ba4\u5206\u7ec4","policy":"4","timer_

  • Python解析json之ValueError: Expecting property name enclosed in double quotes: line 1 column 2(char 1)

    前言 在Python中提供了json包来方便快捷的解析json字串的转换过程,但是碰到了一个比较奇怪的问题,就是不太正确的json串如何来解析? 1. 问题的提出 今天在处理一个http请求的响应json之时,基于python进行解析,碰到了如下错误: Traceback (most recent call last): File "<ipython-input-16-bff463ed9408>", line 1, in <module> json.loads(

  • Python 和 JS 有哪些相同之处

    [嵌牛导读]Python 是一门运用很广泛的语言,自动化脚本.爬虫,甚至在深度学习领域也都有 Python 的身影.作为一名前端开发者,也了解 ES6 中的很多特性借鉴自 Python (比如默认参数.解构赋值.Decorator等),同时本文会对 Python 的一些用法与 JS 进行类比.不管是提升自己的知识广度,还是更好地迎接 AI 时代,Python 都是一门值得学习的语言. [嵌牛鼻子]python与JS的相似之处 [嵌牛提问]python与JS有哪些相似呢? [嵌牛正文] 数据类型

  • python解决js文件utf-8编码乱码问题(推荐)

    html文件中引入js文件,显示乱码! js文件为utf-8 编码(无bom)  ,此时只要将js文件转成utf-8 BOM编码就可以解决了 可以使用notepad++转码 也可以使用下面的python代码批量转码 # -*- coding:utf-8 -*- import os,sys import chardet def convert( filename, in_enc = "GBK", out_enc="UTF-8" ): try: print("

  • python和js交互调用的方法

    后台代码都是利用的 1.[get方式]使用jquery的get json与后台交互 前端js代码片段 var data= { 'a': $('input[name="a"]').val(), 'b': $('input[name="b"]').val() } $.getJSON($SCRIPT_ROOT + '/_add_numbers',data, function(data) { $('#result').text(data.result); $('input[

  • python与js主要区别点总结

    数据类型 js和python都是动态语言,a = 1; a = 'abc',a这个变量是动态的,类型是随时可以被更改的.而在java中就是静态语言变量,int a = 1:a = 'abc' 就会报错. 基本命令 1.输出 js里面的console.log().document.write().window.alert().document.writeIn() python里面是print() 2.输入 js里面是window.prompt() python里面是input() 3.加注释 js

  • 如何用Python和JS实现的Web SSH工具

    这个工具是使用Python开发,可以从下面地址了解详情. 官网: https://pypi.org/project/webssh/ webssh这个工具可以干啥: 在linux机器上安装python环境,并且使用命令pip3 install webssh,装上这个模块 我们就可以在l浏览器web页面登录我们的linux机器,是不是很强大! 功能: 1.支持SSH密码验证,包括空密码. 2.支持SSH公钥认证,包括DSA RSA ECDSA Ed25519密钥. 3.支持加密密钥. 4.支持全屏终

  • python 调用js的四种方式

    1. 前言 日常 Web 端爬虫过程中,经常会遇到参数被加密的场景,因此,我们需要分析网页源代码 通过调式,一层层剥离出关键的 JS 代码,使用 Python 去执行这段代码,得出参数加密前后的 Python 实现 本文将聊聊利用 Python 调用 JS 的4种方式 2. 准备 以一段简单的 JS 脚本为例,将代码写入到文件中 //norm.js //计算两个数的和 function add(num1, num2) {     return num1 + num2; } 其中,定义了一个方法,

  • python执行js代码的方法

    什么是js代码混淆? 正常代码 我们现在看一段js代码,代码逻辑很简单,就是拼接时间返回. function formatDate(now) { var now = new Date(1230999938); var year=now.getFullYear(); var month=now.getMonth()+1; var date=now.getDate(); var hour=now.getHours(); var minute=now.getMinutes(); var second=

  • python与js进行MD5取hash有什么不同

    前言: 做渗透测试发现前端关键字进行了加密,并且对传递的参数进行签名,这导致我不能进行更改参数的值,本来打算使用JSforward进行绕过,结果尝试失败,于是最终还是通过python来写加密方法进行测试.js签名方法已经找到了,是通过MD5进行签名,进行md5时会加入服务器发放的AES秘钥(密码由AES加密),并且秘钥为固定秘钥,因此这里难度不大,但是遇到一个坑,那就python和js对json进行md5取hash,MD5结果值不一致,于是在网上寻找方法,最终还是找到了原因,接下来进行记录. 加

  • Python执行js字符串常见方法示例

    目录 方法 1--js2py 2--execjs 3--execjs 方法 执行大型js时有点慢 特殊编码的输入或输出参数会出现报错,解决方法: 可以把输入或输出的参数用base64编码一下.base64都是英文和数字,没有特殊字符了 1--js2py pip insatll js2py # 获取执行JS的环境 context = js2py.EvalJs() # 加载执行 context.execute('放JS字符代码') 2--execjs import execjs print(exec

  • Python和JS反爬之解决反爬参数 signKey

    目录 实战场景 系统分析 实战场景 Python 反爬中有一大类,叫做字体反爬,核心的理论就是通过字体文件或者 CSS 偏移,实现加密逻辑 本次要采集的站点是:54yr55y855S15b2x(Base64 加密) 站点地址为:https%3A%2F%2Fmaoyan.com%2Ffilms%2F522013(URL 编码) 上述地址打开之后,用开发者工具选中某文字之后,会发现 Elements 中,无法从源码读取到数据, 如下图所示: 类似的所有场景都属于字体编码系列,简单理解就是: 服务器源

随机推荐