最近由于事情的需要开始开拓一些Python的对象,由于之前一直在利用Javascript,所以会不自觉的利用一些Javascript的观念,语法什么的,常常掉到坑里。我以为对付从Javascript转到Python,有须要总结一下它们之间的差别。
根基观念
Python和Javascript都是剧本语言,所以它们有许多配合的特性,都需要表明器来运行,都是动态范例,都支持自动内存打点,都可以挪用eval()来执行剧本等等剧本语言所共有的特性。
然而它们也有很大的区别,Javascript这设计之初是一种客户端的剧本语言,主要应用于欣赏器,它的语法主要警惕了C,而Python由于其“优雅”,“明晰”,“简朴”的设计而广受接待,被应用于教诲,科学计较,web开拓等差异的场景中。
编程范式
Python和Javascript都支持多种差异的编程范式,在面向工具的编程上面,它们有很大的区别。Javascript的面向工具是基于原型(prototype)的, 工具的担任是由原型(也是工具)建设出来的,由原型工具建设出来的工具担任了原型链上的要领。而Python则是中规中矩的基于类(class)的担任,并天然的支持多态(polymophine)。
OO in Pyhton
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 Javascript 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包支持多线程。
不行改变范例 (immutable type)
在Python中,有的数据范例是不行改变的,也就意味着这种范例的数据不能被修改,所有的修改城市返回新的工具。而在Javascript中所有的数据范例都是可以改变的。Python引入不行改变范例我认为是为了支持线程安详,而因为Javascript是单线程模子,所以没有须要引入不行改变范例。
虽然在Javascript可以界说一个工具的属性为只读。
var obj = {};Object.defineProperty(obj, "prop", { value: "test", writable: false});
在ECMAScript5的支持中,也可以挪用Object的freeze要领来是工具变得不行修改。
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)。
#p#分页标题#e#
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中变量的声明和初始化
v1; v2 = null; var v3; var v4 = null; var v5 = 'something';
在如上的代码中v1是全局变量,未初始化,值为undefined;v2是全局变量,初始化为空值;v3为局部未初始化变量,v4是局部初始化为空值的变量;v5是局部已初始化为一个字符处的变量。
Python中变量的声明和初始化
v1 = None
v2 = 'someting'
Python中的变量声明和初始化就简朴了很多。当在Python中会见一个不存在的变量时,会抛出NameError的异常。当会见工具可能字典的值不存在的时候,会抛出AttributeError可能KeyError。因此判定一个值是否存在在Javascript和Python中需要纷歧样的方法。
Javascript中查抄某变量的存在性:
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中查抄某变量的存在性:
try: v except NameError ## do something if v does not exist
在Python中也可以通过查抄变量是不是存在于局部locals()可能全局globals()来判定是否存在该变量。
范例查抄
Javascript可以通过typeof来得到某个变量的范例:
typeof in Javascript 的例子:
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来得到数据的范例。
>>> type([]) is list True >>> type({}) is dict True >>> type('') is str True >>> type(0) is int True
同时也可以通过isinstance()来判定类的范例
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
#p#分页标题#e#
可是留意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气势气魄
def func(list): for i in range(0,len(list)): print list[i] Javascript气势气魄 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,凡是的写法是
(A and B) or C
因为这样写有必然的缺陷,也可以写作
B if A else C
Python对赋值操纵的一个重要的改造是不答允赋值操纵返回赋值的功效,这样做的长处是制止呈此刻应该利用相等判定的时候错误的利用了赋值操纵。因为这两个操纵符实在太像了,并且从自然语言上来说它们也没有区别。
++运算符
Python不支持++运算符,没错你再也不需要按照++标记在变量的阁下位置来思考到底是先加一再赋值呢照旧先赋值再加一。
持续赋值
操作元组(tuple),Python可以一次性的给多个变量赋值
(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)
函数参数
Python的函数参数支持定名参数和可选参数(提供默认值),利用起来很利便,Javascript不支持可选参数和默认值(可以通过对arguments的理会来支持)
def info(object, spacing=10, collapse=1):
… …
其它
当即挪用函数表达式 (IIFE)
Javascript的一个利便的特性是可以当即挪用一个方才声明的匿名函数。也有人称之为自挪用匿名函数。
下面的代码是一个module模式的例子,利用闭包来生存状态实现精采的封装。这样的代码可以用在无需重用的场所。
var counter = (function(){ var i = 0; return { get: function(){ return i; }, set: function( val ){ i = val; }, increment: function() { return ++i; } }; }());
Python没有相应的支持。
生成器和迭代器(Generators & Iterator)
在我打仗到的Python代码中,大量的利用这样的生成器的模式。
#p#分页标题#e#
Python生成器的例子
# 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 迭代器和生成器的例子。
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()); }
列表(字典、荟萃)映射表达式 (List、Dict、Set Comprehension)
Python的映射表达式可以很是利便的辅佐用户结构列表、字典、荟萃等内置数据范例。
下面是列表映射表达式利用的例子:
>>> [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
var numbers = [1, 2, 3, 4]; var doubled = [i * 2 for (i of numbers)];
Lamda表达式 (Lamda Expression )
Lamda表达式是一种匿名函数,基于著名的λ演算。很多语言诸如C#,Java都提供了对lamda的支持。Pyhton就是个中之一。Javascript没有提供原生的Lamda支持。可是有第三方的Lamda包。
g = lambda x : x*3
装饰器(Decorators)
Decorator是一种设计模式,大部门语言都可以支持这样的模式,Python提供了原生的对该模式的支持,算是一种对措施员的便利把。
Decorator的用法如下。
@classmethod def foo (arg1, arg2): ....