最近因为工做的须要开始开发一些Python的东西,因为以前一直在使用Javascript,因此会不自觉的使用一些Javascript的概念,语法什么的,常常掉到坑里。我以为对于从Javascript转到Python,有必要总结一下它们之间的差别。javascript
Python和Javascript都是脚本语言,因此它们有不少共同的特性,都须要解释器来运行,都是动态类型,都支持自动内存管理,均可以调用eval()来执行脚本等等脚本语言所共有的特性。java
然而它们也有很大的区别,Javascript这设计之初是一种客户端的脚本语言,主要应用于浏览器,它的语法主要借鉴了C,而Python因为其“优雅”,“明确”,“简单”的设计而广受欢迎,被应用于教育,科学计算,web开发等不一样的场景中。python
Python和Javascript都支持多种不一样的编程范式,在面向对象的编程上面,它们有很大的区别。Javascript的面向对象是基于原型(prototype)的, 对象的继承是由原型(也是对象)建立出来的,由原型对象建立出来的对象继承了原型链上的方法。而Python则是中规中矩的基于类(class)的继承,并自然的支持多态(polymophine)。程序员
OO in Pyhtonweb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class
Employee:
'Common base class for all employees'
empCount
=
0
##类成员
def
__init__(
self
, name, salary):
self
.name
=
name
self
.salary
=
salary
Employee.empCount
+
=
1
def
displayCount(
self
):
print
"Total Employee %d"
%
Employee.empCount
def
displayEmployee(
self
):
print
"Name : "
,
self
.name,
", Salary: "
,
self
.salary
## 建立实例
ea
=
Employee(
"a"
,
1000
)
eb
=
Employee(
"b"
,
2000
)
|
OO in Javascriptexpress
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var
empCount = 0;
//构造函数
function
Employee(name, salary){
this
.name = name;
this
.salary = salary;
this
.empCount += 1;
}
Employee.prototype.displayCount =
function
(){
console.log(
"Total Employee "
+ empCount );
}
Employee.prototype.displayEmployee =
function
(){
console.log(
"Name "
+
this
.name +
", Salary "
+
this
.salary );
}
//建立实例
var
ea =
new
Employee(
"a"
,1000);
var
eb =
new
Employee(
"b"
,2000);
|
由于是基于对象的继承,在Javascript中,咱们没有办法使用类成员empCount,只好声明了一个全局变量,固然实际开发中咱们会用更合适的scope。注意Javascript建立对象须要使用new关键字,而Python不须要。编程
除了原生的基于原型的继承,还有不少利用闭包或者原型来模拟类继承的Javascript OO工具,由于不是语言自己的属性,咱们就不讨论了。设计模式
在Javascript的世界中是没有多线程的概念的,并发使用过使用事件驱动的方式来进行的, 全部的JavaScript程序都运行在一个线程中。在HTML5中引入web worker能够并发的处理任务,但没有改变Javascript单线程的限制。浏览器
Python经过thread包支持多线程。安全
在Python中,有的数据类型是不可改变的,也就意味着这种类型的数据不能被修改,全部的修改都会返回新的对象。而在Javascript中全部的数据类型都是能够改变的。Python引入不可改变类型我认为是为了支持线程安全,而由于Javascript是单线程模型,因此没有必要引入不可改变类型。
固然在Javascript能够定义一个对象的属性为只读。
1
2
3
|
var
obj = {};Object.defineProperty(obj,
"prop"
, {
value:
"test"
,
writable:
false
});
|
在ECMAScript5的支持中,也能够调用Object的freeze方法来是对象变得不可修改。
1
|
Object.freeze(obj)
|
Javascript的数据类型比较简单,有object、string、boolean、number、null和undefined,总共六种
Python中一切均为对象,像module、function、class等等都是。
Python有五个内置的简单数据类型bool、int、long、float和complex,另外还有容器类型,代码类型,内部类型等等。
Javascript有true和false。Python有True和False。它们除了大小写没有什么区别。
Javascript采用UTF16编码。
Python使用ASCII码。须要调用encode、decode来进行编码转换。使用u做为前缀能够指定字符串使用Unicode编码。
Javascript中全部的数值类型都是实现为64位浮点数。支持NaN(Not a number),正负无穷大(+/-Infiity)。
Python拥有诸多的数值类型,其中的复数类型很是方便,因此在Python在科研和教育领域很受欢迎。这应该也是其中一个缘由吧。Python中没有定义NaN,除零操做会引起异常。
Javascript内置了array类型(array也是object)
Python的列表(List)和Javascript的Array比较接近,而元组(Tuple)能够理解为不可改变的列表。
除了求长度在Python中是使用内置方法len外,基本上Javascript和Python都提供了相似的方法来操做列表。Python中对列表下标的操做很是灵活也很是方便,这是Javascript所没有的。例如l[5:-1],l[:6]等等。
Javascript中大量的使用{}来建立对象,这些对象和字典没有什么区别,可使用[]或者.来访问对象的成员。能够动态的添加,修改和删除成员。能够认为对象就是Javascript的字典或者哈希表。对象的key必须是字符串。
Python内置了哈希表(dictS),和Javascript不一样的是,dictS能够有各类类型的key值。
Javascript定义了两种空值。 undefined表示变量没有被初始化,null表示变量已经初始化可是值为空。
Python中不存在未初始化的值,若是一个变量值为空,Python使用None来表示。
Javascript中变量的声明和初始化
1
2
3
4
5
|
v1;
v2 =
null
;
var
v3;
var
v4 =
null
;
var
v5 =
'something'
;
|
在如上的代码中v1是全局变量,未初始化,值为undefined;v2是全局变量,初始化为空值;v3为局部未初始化变量,v4是局部初始化为空值的变量;v5是局部已初始化为一个字符处的变量。
Python中变量的声明和初始化
1
2
|
v1
=
None
v2
=
'someting'
|
Python中的变量声明和初始化就简单了许多。当在Python中访问一个不存在的变量时,会抛出NameError的异常。当访问对象或者字典的值不存在的时候,会抛出AttributeError或者KeyError。所以判断一个值是否存在在Javascript和Python中须要不同的方式。
Javascript中检查某变量的存在性:
1
2
3
4
5
6
7
|
if
(!v ) {
// do something if v does not exist or is null or is false
}
if
(v === undefined) {
// do something if v does not initialized
}
|
注意使用!v来检查v是否初始化是有歧义的由于有许多种状况!v都会返回true
Python中检查某变量的存在性:
1
2
3
4
|
try
:
v
except
NameError
## do something if v does not exist
|
在Python中也能够经过检查变量是否是存在于局部locals()或者全局globals()来判断是否存在该变量。
Javascript能够经过typeof来得到某个变量的类型:
typeof in Javascript 的例子:
1
2
3
4
5
6
7
8
|
typeof
3
// "number"
typeof
"abc"
// "string"
typeof
{}
// "object"
typeof
true
// "boolean"
typeof
undefined
// "undefined"
typeof
function
(){}
// "function"
typeof
[]
// "object"
typeof
null
// "object"
|
要很是当心的使用typeof,从上面的例子你能够看到,typeof null竟然是object。由于javscript的弱类型特性,想要得到更实际的类型,还须要结合使用instanceof,constructor等概念。具体请参考这篇文章
Python提供内置方法type来得到数据的类型。
1
2
3
4
5
6
7
8
|
>>>
type
([])
is
list
True
>>>
type
({})
is
dict
True
>>>
type
('')
is
str
True
>>>
type
(
0
)
is
int
True
|
同时也能够经过isinstance()来判断类的类型
1
2
3
4
5
6
7
8
|
class
A:
pass
class
B(A):
pass
isinstance
(A(), A)
# returns True
type
(A())
=
=
A
# returns True
isinstance
(B(), A)
# returns True
type
(B())
=
=
A
# returns False
|
可是注意Python的class style发生过一次变化,不是每一个版本的Python运行上述代码的行为都同样,在old style中,全部的实例的type都是‘instance’,因此用type方法来检查也不是一个好的方法。这一点和Javascript很相似。
当操做不一样类型一块儿进行运算的时候,Javascript老是尽量的进行自动的类型转换,这很方便,固然也很容易出错。尤为是在进行数值和字符串操做的时候,一不当心就会出错。我之前常常会计算SVG中的各类数值属性,诸如x,y坐标之类的,当你一不当心把一个字符串加到数值上的时候,Javascript会自动转换出一个数值,每每是NaN,这样SVG就彻底画不出来啦,由于自动转化是合法的,找到出错的地方也很是困难。
Python在这一点上就很是的谨慎,通常不会在不一样的类型之间作自动的转换。
Python使用缩进来决定逻辑行的结束很是具备创造性,这也许是Python最独特的属性了,固然也有人对此颇具微词,尤为是须要修改重构代码的时候,修改缩进每每会引发不小的麻烦。
Javascript虽然名字里有Java,它的风格也有那么一点像Java,但是它和Java就比如雷峰塔和雷锋同样,真的没有半毛钱的关系。到时语法上和C比较相似。这里必需要提到的是coffeescript做为构建与Javascript之上的一种语言,采用了相似Python的语法风格,也是用缩进来决定逻辑行。
Python风格
1
2
3
|
def
func(
list
):
for
i
in
range
(
0
,
len
(
list
)):
print
list
[i]
|
Javascript风格
1
2
3
4
5
|
function
funcs(list) {
for
(
var
i=0, len = list.length(); i < len; i++) {
console.log(list[i]);
}
}
|
从以上的两个代码的例子能够看出,Python确实很是简洁。
Javascript的做用域是由方法function来定义的,也就是说同一个方法内部拥有相同的做用域。这个严重区别与C语言使用{}来定义的做用域。Closure是Javascript最有用的一个特性。
Python的做用域是由module,function,class来定义的。
Python的import能够很好的管理依赖和做用域,而Javascript没有原生的包管理机制,须要借助AMD来异步的加载依赖的js文件,requirejs是一个经常使用的工具。
Javascript使用=赋值,拥有判断相等(==)和全等(===)两种相等的判断。其它的逻辑运算符有&& 和||,和C语言相似。
Python中没有全等,或和与使用的时and 和 or,更接近天然语言。Python中没有三元运算符 A :B ?C,一般的写法是
1
|
(A
and
B)
or
C
|
由于这样写有必定的缺陷,也能够写做
1
|
B
if
A
else
C
|
Python对赋值操做的一个重要的改进是不容许赋值操做返回赋值的结果,这样作的好处是避免出如今应该使用相等判断的时候错误的使用了赋值操做。由于这两个操做符实在太像了,并且从天然语言上来讲它们也没有区别。
Python不支持++运算符,没错你不再须要根据++符号在变量的左右位置来思考究竟是先加一再赋值呢仍是先赋值再加一。
利用元组(tuple),Python能够一次性的给多个变量赋值
1
|
(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY)
=
range
(
7
)
|
Python的函数参数支持命名参数和可选参数(提供默认值),使用起来很方便,Javascript不支持可选参数和默认值(能够经过对arguments的解析来支持)
1
2
|
def
info(
object
, spacing
=
10
, collapse
=
1
):
... ...
|
Javascript的一个方便的特性是能够当即调用一个刚刚声明的匿名函数。也有人称之为自调用匿名函数。
下面的代码是一个module模式的例子,使用闭包来保存状态实现良好的封装。这样的代码能够用在无需重用的场合。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var
counter = (
function
(){
var
i = 0;
return
{
get:
function
(){
return
i;
},
set:
function
( val ){
i = val;
},
increment:
function
() {
return
++i;
}
};
}());
|
Python没有相应的支持。
在我接触到的Python代码中,大量的使用这样的生成器的模式。
Python生成器的例子
1
2
3
4
5
6
7
8
|
# a generator that yields items instead of returning a list
def
firstn(n):
num
=
0
while
num < n:
yield
num
num
+
=
1
sum_of_first_n
=
sum
(firstn(
1000000
))
|
Javascript1.7中引入了一些列的新特性,其中就包括生成器和迭代器。然而大部分的浏览器除了Mozilla(Mozilla基本上是在本身玩,下一代的Javascript标准应该是ECMAScript5)都不支持这些特性
Javascript1.7 迭代器和生成器的例子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function
fib() {
var
i = 0, j = 1;
while
(
true
) {
yield i;
var
t = i;
i = j;
j += t;
}
};
var
g = fib();
for
(
var
i = 0; i < 10; i++) {
console.log(g.next());
}
|
Python的映射表达式能够很是方便的帮助用户构造列表、字典、集合等内置数据类型。
下面是列表映射表达式使用的例子:
1
2
3
4
5
6
|
>>> [x
+
3
for
x
in
range
(
4
)]
[
3
,
4
,
5
,
6
]
>>> {x
+
3
for
x
in
range
(
4
)}
{
3
,
4
,
5
,
6
}
>>> {x: x
+
3
for
x
in
range
(
4
)}
{
0
:
3
,
1
:
4
,
2
:
5
,
3
:
6
}
|
Javascript1.7开始也引入了Array Comprehension
1
2
|
var
numbers = [1, 2, 3, 4];
var
doubled = [i * 2
for
(i of numbers)];
|
Lamda表达式是一种匿名函数,基于著名的λ演算。许多语言诸如C#,Java都提供了对lamda的支持。Pyhton就是其中之一。Javascript没有提供原生的Lamda支持。可是有第三方的Lamda包。
1
|
g
=
lambda
x : x
*
3
|
Decorator是一种设计模式,大部分语言均可以支持这样的模式,Python提供了原生的对该模式的支持,算是一种对程序员的便利把。
Decorator的用法以下。
1
2
3
|
@classmethod
def
foo (arg1, arg2):
....
|
更多decorator的内容,请参考https://wiki.python.org/moin/PythonDecorators
本人对Javascript和Python的认识有限,欢迎你们提出宝贵意见。