Python 和 JS 有哪些相同之处


Posted in Python onNovember 23, 2017

【嵌牛导读】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 有哪些相同之处,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python写的PHPMyAdmin暴力破解工具代码
Aug 06 Python
Python中random模块用法实例分析
May 19 Python
python 容器总结整理
Apr 04 Python
python内置函数:lambda、map、filter简单介绍
Nov 16 Python
python3实现字符串的全排列的方法(无重复字符)
Jul 07 Python
pyqt弹出新对话框,以及关闭对话框获取数据的实例
Jun 18 Python
Python处理时间日期坐标轴过程详解
Jun 25 Python
Python实现12306火车票抢票系统
Jul 04 Python
Win10环境python3.7安装dlib模块趟过的坑
Aug 01 Python
Python Opencv提取图片中某种颜色组成的图形的方法
Sep 19 Python
如何用Python绘制3D柱形图
Sep 16 Python
Python实现双向链表基本操作
May 25 Python
深入理解Python分布式爬虫原理
Nov 23 #Python
Python实现希尔排序算法的原理与用法实例分析
Nov 23 #Python
Python 用Redis简单实现分布式爬虫的方法
Nov 23 #Python
Python3 伪装浏览器的方法示例
Nov 23 #Python
python学习笔记之列表(list)与元组(tuple)详解
Nov 23 #Python
python数字图像处理之高级滤波代码详解
Nov 23 #Python
Python3网络爬虫之使用User Agent和代理IP隐藏身份
Nov 23 #Python
You might like
PHP文件大小格式化函数合集
2014/03/10 PHP
自定义session存储机制避免会话保持问题
2014/10/08 PHP
基于php中echo用逗号和用点号的区别详解
2018/01/23 PHP
一句话JavaScript表单验证代码
2009/08/02 Javascript
简单时间提示DEMO从0开始一直进行计时
2013/11/19 Javascript
javascript关于继承的用法汇总
2014/12/20 Javascript
javascript中JSON对象与JSON字符串相互转换实例
2015/07/11 Javascript
AngularJS轻松实现双击排序的功能
2016/08/30 Javascript
js实现HashTable(哈希表)的实例分析
2016/11/21 Javascript
bootstrap选项卡使用方法解析
2017/01/11 Javascript
微信小程序 image组件binderror使用例子与js中的onerror区别
2017/02/15 Javascript
bootstrap paginator分页前后台用法示例
2017/06/17 Javascript
vue中使用refs定位dom出现undefined的解决方法
2017/12/21 Javascript
详解如何使用koa实现socket.io官网的例子
2018/11/04 Javascript
vue-cli中安装方法(图文详细步骤)
2018/12/12 Javascript
[01:45]2014DOTA2 TI预选赛预选赛 大神专访第二弹!
2014/05/20 DOTA
分享一个可以生成各种进制格式IP的小工具实例代码
2017/07/28 Python
Windows下python3.6.4安装教程
2018/07/31 Python
Python I/O与进程的详细讲解
2019/03/08 Python
Python中使用pypdf2合并、分割、加密pdf文件的代码详解
2019/05/21 Python
pip 安装库比较慢的解决方法(国内镜像)
2019/10/06 Python
python socket通信编程实现文件上传代码实例
2019/12/14 Python
python实现四人制扑克牌游戏
2020/04/22 Python
如何实现在jupyter notebook中播放视频(不停地展示图片)
2020/04/23 Python
python中count函数知识点浅析
2020/12/17 Python
Ralph Lauren法国官网:美国高品味时装品牌
2017/12/08 全球购物
乌克兰鞋类购物网站:Eobuv.com.ua
2020/11/28 全球购物
报关简历自我评价怎么写
2013/09/19 职场文书
大学本科毕业生求职简历的自我评价
2013/10/09 职场文书
家具商场的活动方案
2014/08/16 职场文书
党组织领导班子整改方案
2014/10/25 职场文书
2015年双拥工作总结
2015/04/08 职场文书
劳保用品管理制度范本
2015/08/06 职场文书
MySQL中存储时间的最佳实践指南
2021/07/01 MySQL
《王者天下》第4季首话新剧照 4月9日正式开播
2022/04/07 日漫
python缺失值填充方法示例代码
2022/12/24 Python