张 颖,软件工程师,IBM
简介:?Python 和 Perl 作为主流脚本语言中的成员,在语法等方面有很多相似之处,却又存在一定的差异。本文通过对这两种语言的比较,从而使得相关开发人员可以更深刻的了解和掌握这两种语言
关于?Perl?与?Python?的起源和特点
Perl?是?Practical Extraction and Report Language?的简称,由?1987?年?Larry Wall?创建,最初的目的是为了在?UNIX?上方便处理报表,经过长期的发展已经成为一种全功能的程序设计语言,当前最新的版本为?Perl5.14.1,Perl?作为一种自由而强大的编程语言,其中心思想是:There's More Than One Way To Do It。(不只一种方法來做这件事?),即「?Tim Toady?」。作为一种“胶水型”语言,它具有强大的正则表达式和模式匹配功能以及灵活的数据结构,如动态数组、Hash?等,在语法规则上借鉴了?C/C++、Basic、Pascal?等语言,其不足之处在于存在一些冗余语法,代码的可读性较差。
Python?是一种基于面向对象的解析性交互式的开源编程语言,它起源于?1989?年末由?CWI(阿姆斯特丹国家数学和计算机科学研究所)的研究员?Guido van Rossum?创立,1991?年初公开发行,其开源式的发行方式促进了?Python?的较快发展,目前已经形成了一个强大的社区力量。Python?开发者的哲学是“用一种方法,最好是只有一种方法来做一件事”。Python?具有简单易学、代码规范、语法简单、可移植性强、支持多平台、类库丰富等优点。
Perl?和?Python?都是开源的,但其哲学理念却刚好相反,因此常被人们将这两种语言放在一起进行比较。下面的篇章将从基本数据类型、控制流、函数、面向对象、文本处理等方面对这两种语言进行简单的比较和鉴别。
回页首
Perl?与?Python?的基本数据类型
脚本语言支持多种数据类型,变量无需事先申明,类型根据值来动态确定,一个变量在程序中可以根据上下文环境的不同存储不同类型的值。
Perl?支持的基本数据类型包括:标量、数组、哈希。在定义的时分别用?$、@、%?表示。
1.??????标量?(scalar):标量是?Perl?中最简单的数据类型,大多数标量由数字或字符串组成。其中数字类型如整数、浮点数等,字符串有单引号和双引号内两种形式,对长度没有限制。两者的区别在于在单引号内?n?不代表换行,而代表反斜线和?n?这两个字符,双引号内字符串则可以通过反斜线进行转义。字符串的操作符有?.?拼接操作符和?x?重复操作符等。
2.??????数组?(Arrays):数组用?@?定义,如?my @array=("a","b","c","d");?访问数组的元素用?$array[1]。在?perl?中,数组也可以当做堆栈来处理,支持的操作符包括?pop?和?push,shft?和?unshift。两组操作的区别在于前者对数组的尾部进行处理,而?shift?和?unshift?则针对数组的头部进行处理。pop?得到的是数组的最后一个元素,如?pop(@array)= d,如果数组为空,则返回?undef。而shift(@array)=a。
3.??????哈希:也称作关联数组,是根据关键码值?(Key value)?而直接进行访问的数据结构。用?%?定义,如?%my_hash=(“key1”=>”23”,”name”=>”zhang”,”age”=>”24”),其中键以字符串表示,Hash?可以是任意大小。
与?hash?相关的函数有:
keys:返回?hash?的键列表?my @keylist = keys %hash
value:返回值列表?my @valuelist = values %hash
each:用两个元素的列表返回键值对。
while(($key,$value)= each %hash)
{
print “$key =>$valuen”;
}
Python?支持五种基本数据类型:数字?(Numbers)、字符串?(String)、列表?(List)、元组?(Tuple)?和字典?(Dictionary)。其中数字和字符串和perl?中的标量对应,列表和数组对应,元组可以看做是不可变的列表,字典和?hash?对应。
1.??????数字?(Numbers):Python?支持五种基本数字类型,分别为?int(?有符号整数?)?、long(?长整数?)?、bool(?布尔值?)?、float(?浮点数?)、complex(?复数?)。
2.??????字符串?(String):Python?与?Perl?一样也支持单引号和双引号字符串,但与?Perl?不同,转义字符在单引号中也会起作用。同时python?还支持三引号字符串,它允许一个字符串跨多行,字符串中可以包含换行符,制表符以及其他特殊字符。三引号字符串常用于注释或者形成文档。字符串支持成员操作符?in,not in,连接操作符?+?以及重复操作符?*。Python?字符串可以当做?list,支持切片操作符?[],[:]?和反向索引。如下:?
如?aString=”abcd”;则?aString[0]?的值为?a,aString[1:3]=bc,反向索引?aString[-1]=d
3.??????列表?(List):Pyhon?中的列表与?Perl?中的数组相对应。列表的定义使用?[].?如?li = ["a","mpilgrim","z","example"]?,支持动态增加和删除元素以及切片操作。
增加元素可以使用?li.append(“test”),li.insert(2,”new”)?以及?li.extend([“f”,”ggf”])
删除元素使用?li.remove(“f”)?和?li.pop()?。但需要注意的是?remove?仅删除首次出现的,而?pop?会删除?list?最后的一个元素,然后返回删除的元素的值。
4.??????元组?(Tuple):元组和列表非常相似,但用()表示,并且元组是不可变的。
5.??????字典?(Dictionary):字典跟?Perl?中的?hash?一样,定义了键值对之间一对一的关系,变量可以任意取名,Python?会在内部记录其数据类型。定义一个字典:D={“name”:”Jon”,”Family”:”SH”},?字典中的?key?是不能重复的,并且大小写敏感,同时字典中的元素是无序的。字典也支持增删操作,往字典中添加元素?D[“age”]=23,?删除元素?del D['name'],如果需要删除所有元素可以使用?D.clear(),?或者?del D?删除整个字典。
回页首
Perl?与?Python?的控制结构
在控制结果方面,Perl?较?Python?丰富,除了支持传统的?if?、while?、for?控制结构,还支持?until?、unless?、foreach?等,Python?的控制结构相对要少一些,但已经能够满足语言的要求。本节对这些控制结构进行详细比较。
If?控制结构:
Perl?与?Python?都支持?if?、if-else?、if-else if- else?三种结构,两者在语法上基本类似,但与?Python?不同的是?Perl?中没有?boolean?类型,零和空表示?False,其余表示?True,而?Python?中除了''、""、0、()、[]、{}、None?为?False?之外,其他的都是?True。同时?Python?直接用缩进表示?block?块。
表?1. if?控制结构
Perl |
Python |
if |
if (expression) { true_statement; } |
if expression: if_suite |
if-else |
if (expression) { true_statement; } |
if expression: if_suite else: else_suite |
If-else if-else |
if (expression_A) { A_true_statement; } elseif (expression_B) { B_true_statement; } else { false_statement; } |
if expression1: if_suite elif expression2: elif_suite else: else_suite |
Perl?中还支持?unless?条件控制语句,基本语法如下:
unless (expression) {?
stmt_1; }
unless?和?if?不同之处在于当条件表达式的值为假的时候才执行,同时?unless?后面还能跟?else?语句。如:
?unless($mon =~/^Feb/){??print “This month has at least thirty days.n”;??}else{??print “Do you see what's going on here?n”;??} |
循环控制结构:
1.??????For?循环:
Perl?中的?for?循环除了支持传统的?for?循环,即?for (?表达式?1;?表达式?2;?表达式?3)?,还支持?foreach?语句,基本语法为:
????????? ?foreach?$i (@aList) {??????????????????? ?stmt_1;??????????????????? ?} |
python?不支持传统的?for?循环,但是提供了强大的循环结构可以遍历序列成员,同时?for?循环后面也可以接?else?语句,基本语法如下:
?for inter_var in iterable:??????????????????? ?suite_to_repeat??else:?????????? ???????else_statement |
1.??????while?循环
Perl?循环控制结果还支持?while?和?do-while?以及?until?形式,until?与?while?结构相似,区别在于?unitl?会在条件为假的时候重复执行。until?语法如下:
?until(expression)??{?????statement;??} |
而?python?只支持?while?形式,但?python?可以在?while?后面接?else?语句。语法如下:
?While condition:??????????????????? ?statements??else:??????????????????? ?statements |
循环控制符
Perl?有三个循环控制操作符,分别为?Last?、next?、redo。
1.??????last:立即终止循环,类似于?c?中的?break。在多层循环中,只对?last?所在的当前循环块有效;
2.??????next:立刻结束当前这次迭代;
3.??????redo:将控制返回本循环的顶端,不经过条件测试也不会进去下一次迭代循环,而是重新执行本循环块。它与?next?最大的区别在于?next?会正常继续下一次迭代,而?redo?会重新执行本次迭代。
Python?也有三个循环控制操作符,分别为?break?、continue?、pass?语句。
1.??????break:与?C?中的?break?类似;
2.??????continue:continue?语句并不会退出循环结构,而是立即结束本次循环,重新开始下一轮循环,也就是说,跳过循环体中在continue?语句之后的所有语句,继续下一轮循环;
3.??????pass:一般作为占位符或者创建占位程序,pass?语句不会执行任何操作。
回页首
Perl?与?Python?的函数
Perl?和?Python?都支持函数,可以传递参数以及在程序中对函数进行调用等。下面从函数的定义,调用,返回值以及参数传递等方面对这两者进行比较。
表?2. Perl?与?Python?函数比较
Python |
定义 |
1.?????? 基本语法: sub functionName{ ?statement; [return value] ?} |
1.??????基本语法: def functionName(arg1,arg2,[...]): statement [return value] 2.??????内嵌函数: Python?支持内嵌函数?,?其方法是在外部函数的定义体内定义函数?,?但整个函数体都在外部函数的作用域之内?. def outfun(): def innerfun(): Print “inner fun test” print “out fun test” |
返回值 |
使用?return?语句显示返回;如果没有?return,默认返回最后一次运算的结果 |
使用?return?语句显示返回,没有?return?语句,默认返回为?None。如果函数返回多个对象,python?把他们聚集起来并以一个元组返回。 |
调用 |
&?函数名(参数?1,参数?2,...),如果声明在前,可以省略&。如果用户所定义的子过程与内置函数重名,则不能省略?&。 如下例必须使用?&chomp?调用: sub chomp{ print “it is my chompn”; } |
1.??????直接采用?函数名(参数?1,参数?2.....) 2.??????函数名(参数名?1=?值,参数名?2=?值?.......) |
函数参数 |
1.??????在子程序调用的后面加上被括号圈引的列表表达式即可,所有的参数都会自动存储为?@_?中,其中第一个参数为?$_[0],?第二个参数存储?$_[1]。 2.??????传递引用,在参数前加入??表示为引用 |
1.??????按照参数声明的关键字顺序直接传递; 2.??????通过关键字参数?testFun(par1=“2”,par2=“45”) 3.??????默认参数: > Python?在传递参数的时候支持默认参数,规则是所有的位置参数必须出现在任何一个默认参数之前,如? def fun(arg1,defarg1=”var1”,defarg2=”12”),?如果在调用的时候没有给出参数值,则会使用默认值? 4.??????变长参数: 一种方法是利用非关键字可变长参数?,?可变长的参数元组必须在位置和默认参数之后?,?带元组的函数语法如下: def function_name([formal_args,]*vargs_tuple): function_body 其中?*?之后的形参将作为元组传递给函数。
另外一种方法是利用关键字变量参数,区别是在函数的参数变量里使用?**。 def dicVarArgs(arg1,arg2=”default”,**theRest): print 'formal arg1:',arg1 print 'formal arg2:',arg2 for eachXtrArg in theRest.keys(): print 'Xtra arg %s: %s' % (eachXtrArg,str(theRest[eachXtrArg])) |
?
回页首
Perl?与?Python?的包与模块
Perl?程序把变量和子程序的名称存贮到符号表中,Perl?的符号表中名字的集合就称为?Perl?包?(package)。定义语法为:package mypack;每个符号表有其自己的一组变量、子程序名,各组名字是不相关的,因此可以在不同的?Perl?包中使用相同的变量名,而代表的是不同的变量。Perl?模块有两种来源,一种是随?Perl?发行版本一同打包的,另外就是用?CPAN?中下载的。Perl?模块和包的概念并不清晰,两者有时可以混用。在程序中使用模块的操作称为导入模块;导入模块关键字?use;如:use ModuleName;模块被导入后,其中的子程序和变量就可以直接使用了;要取消一个已经导入了的模块,可以使用关键字?no;如:no ModuleName。
一个?.py?文件就是一个?python?模块。把一堆相关的?python?模块放在一个目录下,再加上一个?__init__.py?文件就构成了一个?python?包。在Python?另一个程序中导入模块用?import module?或者?from module import *,两者的区别在于:import module?会导入?module?这个模块里的所有标识,但是这些标识现在都在?module?名字空间下。from module import *?也会导入?module?中所有标识,但是标识放到在当前名字空间里。
导入模块或包按下面顺序进行路径查找:
1.?当前目录?
2.?环境变量?PYTHONPATH?所指的目录列表?3.python?解释器的安装目录
回页首
Perl?与?Python?中的?OOP
在?Perl?中,类是?Perl?包,含有提供对象方法的类,而方法是?Perl?的子程序,类名是其第一个参数,对象是对类中数据项的引用。在?Perl?中创建一个新类,首先要创建一个包,扩展名为?.pm,?在创建?perl?包的时候程序的最后一个必须为"1;";否则该包不会被?Perl?处理。
清单?1.?创建?perl?的类和对象
???????????????????????????????????????package person;??use strict;??sub new {??????????my?$class = shift();??????????print("CLASS =?$classn");??????????my?$self = {};??????????$self->{"name"} = shift();?????????$self->{"sex"} = shift();??????????bless?$self,?$class;??????????return?$self;??}??1; |
其中?new()?方法是对象的构造函数,是创建该类的对象实例必须被调用的,它返回该对象的引用。将类名与引用相结合称为”bless”一个对象,其语法为:bless YeReference [,classname]
YeReference?是对被”祝福”的对象的引用,classname?是可选项,指定对象获取方法的包名,其缺省值为当前包名。也可以通过函数?bless来声明一个构造函数。
?sub new??{?????my?$class = shift;?????my?$self = {};?????bless?$self,?$class;?????return?$self;??} |
创建一个对象可以直接使用?new?关键字。$object = new Person( "mohand","sam",345);
Perl?类中的方法就?Perl?的子函数,规定第一个参数为对象或者被引用的包,分为静态方法和虚方法。?虚方法通常首先把第一个参数?shift?到变量?self?或?this?中,然后将该值作普通的引用使用。一是通过该对象的引用?(?虚方法?),一是直接使用类名?(?静态方法?)。如上例中如果类Person?中有?getContactList?则可以直接使用?$object->getContactList()?来调用该方法。
Perl?支持重载,当两个不同的类中含有相同的方法名称的时候,可以用?::?操作符指定使用哪个类中的方法。
$mess = Qava::grind("whole","lotta","bags");
Qava::grind($mess,"whole","bags");
由于?Perl?采用了简单的、基于引用的垃圾回收系统。Perl?跟踪对象的链接数目,当某对象的最后一个应用释放到内存池时,该对象就自动销毁。因此一般不需要定义类的析构函数。
Perl?通过数组?@ISA?支持继承。
?package Employee;??use Person;??use strict;??our @ISA = qw(Person);??? # inherits from Person |
当子类继承父类的时候,继承了父类的所有方法,但子类也可以覆盖父类的方法。如加入?Employee?想覆盖父类的?getFirstName:
?#!/usr/bin/perl???package Employee;??use Person;??use strict;??our @ISA = qw(Person);??? # inherits from Person???# Override helper function??sub getFirstName {?????my(?$self ) = @_;?????# This is child class function.?????print "This is child class helper functionn";?????return?$self->{_firstName};??}??1; |
调用直接使用?$firstName =?$object->getFirstName();?如果要调用父类的?getFirstName,则可以使用?$object->Person::getFirstName();
在?Python?中创建一个类的基本语法为?:
?class className(bases):??????????????????? ?classBody |
参数?base?可以是一个单继承或者多继承的父类,object?是所有类的父类,位于类继承结构的最上层。类的构造函数为?__init__(),其中构造函数中?self?会作为第一个默认的参数。而类的析构函数则是?__del__(),访问类的方法和属性可以直接使用?.?访问符。
Python?不支持纯虚函数或抽象方法,并且声明和定义没有本质区别。一般或者?Python?类的属性可以通过?__dict__?或者?dict()访问。常见属性有?__name__?,__doc__,__base__,__dict__。Python?中创建一个类的实例,不需要关键之?new,直接使用类名?()?即可。如c=myclass()。
Python?不仅仅支持单继承和多继承,同时还支持方法的覆盖?.
?class P(object):??def foo(self):??print 'Hi,I am P-foo()'?>>> p = P()??>>> p.foo()??Hi,I am P-foo() |
现在创建?C?类?,?继承于?P
?class C(P):??def foo(self):??print 'Hi,I am C-foo()'?>>> c = C()??>>> c.foo()??Hi,I am C-foo() |
当从一个带构造器?__init()_?的类派生,如果在子类中覆盖了?__init__(),当子类被实例化时,基类的?__init__()?方法不会被自动调用。如果必须调用基类的构造方法,可以使用父类名?.__init__(self)?方法或者?super(?子类名,self).__init__()。?如
?def __init__(self):??super(C,self).__init__()??print "calling C's constructor" |
Python?类和实例支持一些内建函数,如
Issubclass(sub,sup):判断一个类是另一个类的子类或子孙类;
isinstance(obj1,obj2):判定一个对象是否是另一个给定类的实例;
回页首
Perl?与?Python?的正则表达式
正则表达式是?perl?比较突出的一大特色,perl?中正则表达式有三种形式:
匹配:m/<regexp>/?(还可以简写为?/<regexp>;/?,略去?m)?替换:s/<pattern>/<replacement>/?,为了语法的简化用/<pattern>/<replacement>/?表示,略去?s
转换:tr/<charClass>/<substituteClass>/?这种形式包含一系列的字符— /<charClass> —同时把它们替换为?<substituteClass>。
表?3. Perl?常用匹配模式
语法 |
说明 |
示例 |
. |
匹配除换行符以外的所有字符 |
b.c?匹配?bac |
x? |
匹配?0?次或一次?x?字符串 |
b?c?匹配?c?或者?bc |
x* |
匹配?0?次或多次?x?字符串,但匹配可能的最少次数 |
b*c?匹配?c?或者?bbc |
x+ |
匹配?1?次或多次?x?字符串,但匹配可能的最少次数 |
b+c?匹配?bc?或者?bbc |
.* |
匹配?0?次或一次的任何字符 |
b.*c?匹配?bgdc?等 |
.+ |
匹配?1?次或多次的任何字符 |
b.+c?匹配?bgc?等 |
{m} |
匹配刚好是?m?个?的指定字符串 |
b{5}c?匹配?bbbbbc |
{m,n} |
匹配在?m?个?以上?n?个?以下?的指定字符串 |
b{1,2}?匹配?b?或者?bb |
{m,} |
匹配?m?个?以上?的指定字符串 |
b{2,}?匹配?bb?或者?bbb等 |
[] |
匹配符合?[]?内的字符 |
b[d]c?匹配?bdc |
[^] |
匹配不符合?[]?内的字符 |
b[^d]c?匹配?bAc |
[0-9] |
匹配所有数字字符 |
b[0-9]c?匹配?b1c |
[a-z] |
匹配所有小写字母字符 |
b[a-z]c?匹配?bac |
^ |
匹配字符开头的字符 |
^perl?匹配以?perl?开头的字符 |
$ |
匹配字符结尾的字符 |
perl$?匹配以?perl?结尾的字符 |
d |
匹配一个数字的字符,和?[0-9]?语法一样 |
bdc?匹配?b1c |
D |
非数字,其他同?d |
bDc?匹配?bAc |
w |
英文字母或数字的字符串,和?[a-zA-Z0-9]?语法一样 |
bwc?匹配?b1c?等 |
W |
非英文字母或数字的字符串,和?[^a-zA-Z0-9]?语法一样 |
bWc?匹配?b c |
s |
空格,和?[ntrf]?语法一样 |
bsc?匹配?b c |
S |
非空格,和?[^ntrf]?语法一样 |
bSc?匹配?bac?等 |
b |
匹配以英文字母?,?数字为边界的字符串 |
bbcb?匹配?bc?但不匹配bca |
B |
匹配不以英文字母?,?数值为边界的字符串 |
saB?将匹配?sand?和Sally?等字符串,而不能匹配?Melissa. |
a|b|c |
匹配符合?a?字符?或是?b?字符?或是?c?字符?的字符串? abc?匹配含有?abc?的字符串 |
匹配?a?或者?b?或者?c?等 |
(pattern) () |
这个符号会记住所找寻到的字符串,是一个很实用的语法。第一个?()?内所找到的字符串变成?$1?这个变量或是?1?变量,第二个?()?内所找到的字符串变成?$2?这个变量或是?2变量,以此类推下去。 |
b(d)c?表示匹配的任何数字将存放与?$1?变量中 |
Python?语言本身不支持正则表达式,依赖?re?模块(python1.5?版本被引入)支持正则表达式。有搜索和匹配两种方法完成匹配模式。re?模块常用的函数和方法有?complie、match、search、find?与?findall?等。在利用?re?进行匹配之前,模式必须被编译成?regex?对象。
表?4. Python?常用匹配模式
示例 |
. |
匹配除换行符?n?以外的任意字符 |
b.c?匹配?bac,bdc |
* |
匹配前一个字符?0?次或多次 |
b*c?匹配?c,或者?bbbc |
+ |
匹配前一个字符?1?次或多次 |
b+c?匹配?bc?或者?bbbc |
? |
匹配前一个字符?0?或?1?次 |
b?c?匹配?c?或者?bc |
{m} |
匹配前一个字符?m?次 |
b{2}c?匹配?bbc |
{m,n} |
匹配前一个字符?m?至?n?次 |
b{2,5}c?匹配?bbc?或者?bbbbc |
[abc] |
匹配?[]?内的任意字符 |
[bc]?匹配?b?或者?c |
d |
匹配数字?[0-9] |
bdc?匹配?b1c?等 |
D |
匹配非数字,等价于?[^d] |
bDc?匹配?bAc |
s |
匹配空白字符 |
bsc?匹配?b c |
S |
匹配非空白字符?[^s] |
bSc?匹配?bac |
w |
匹配?[A-Za-z0-9_] |
bwc?匹配?bAc?等 |
W |
等价于?[^w] |
bWc?匹配?b c |
|
转义字符, |
bc?匹配?bc |
^ |
匹配字符串开头 |
^bc?匹配句首的?bc |
$ |
匹配字符串末尾 |
bc$?匹配以?bc?结尾的字符串 |
A |
仅匹配字符串开头 |
Abc?匹配字符串开头的?bc |
Z |
仅仅匹配字符串末尾 |
bcZ?匹配字符串末尾的?bc |
| |
匹配左右表达式任意一个 |
b|c?匹配?b?或者?c |
?
回页首
Perl?与?Python?中的线程
线程是一个单一的执行流程,它是所有程序执行过程中最小的控制单位,即能被?CPU?所调度的最小任务单元。在?Perl?中一个线程的生命周期包括创建,运行与退出这三个阶段。线程的运行过程与普通函数的执行类似,但新建线程的执行与当前线程的执行是并行的。
在?Perl?中创建线程有两种方法:
清单?2.?使用?threads?包的?create()?方法
??????????????????????????????????????????????? ?use threads;?????????? ?sub say_hello?????????? ?{????????? ????printf("Hello thread! @_.n");?????????? ????return( rand(10) );?????????? ?}?????????? ?my?$t1 = threads->create( &;say_hello,"param1","param2" ); |
清单?3.?使用?async{}?块创建线程
???????????????????????????? ??????????????????? ?#!/usr/bin/perl?????????? ?use threads;?????????? ?my$t4 = async{?????????? ?????????????????? ?printf("Hello thread!n");?????????? ?????????? ?}; |
对于线程的执行控制,有两种方式,一种是?join(),一种是?detach()。所谓?join()?就是在主线程中等待子线程的执行返回值,然后再继续执行后续代码,而在调用线程的?join()?方法之前,子线程与主线程的执行是分开的。而?detach()?则是告诉解释器主线程不关心子线程的执行结果,所以该子线程在完成任务之后就是自动退出,同时释放自己所占有的资源,而不用主线程再操心。
Perl?默认任何数据结构都不是共享的,任何新创建的线程都有当前数据的私有拷贝。如果要共享数据,必须使用?threads::shard?进行显示声明。
如:
????????? ?my?$var?? :shared? = 0;?????? ??????? ?# use :share tag to define?????????? ?my @array :shared = (); ????????????? ?# use :share tag to define?????????? ?my %hash = ();?????????? ?share(%hash);????????????????? ???????? ?# use share() funtion to define |
同时?Perl?线程还支持锁机制,可以使用?lock?方法实现线程间共享数据的锁机制。Perl?中的?Thread::Semaphore?包为线程提供了信号量的支持,Thread::Queue?包为线程提供了线程安全的队列支持。更多使用读者可以自行查阅相关文档。
Python?提供了几个用于多线程编程的模块,包括?thread,threading?和?Queue?等。thread?和?threading?模块允许程序员创建和管理线程。thread?模块提供了基本的线程和锁的支持,而?threading?提供了更高级别,功能更强的线程管理的功能。Queue?模块允许用户创建一个可以用于多个线程之间共享数据的队列数据结构。
Python?的线程创建也有两种方式,一是利用?thread?模块的?start_new_thread()?函数来产生新线程。
????????? ?import time?????????? ?import thread?????????? ?def timer(no,interval):?????????? ????cnt = 0?????????? ????while cnt<10:?????????? ????????print 'Thread:(%d) Time:%s/n'%(no,time.ctime())????????? ????????time.sleep(interval)?????????? ????????cnt+=1?????????? ????thread.exit_thread()????????? ?def test(): ????? ?#Use thread.start_new_thread() to create 2 new threads?????????? ????thread.start_new_thread(timer,(1,1))?????????? ????thread.start_new_thread(timer,(2,2))?????????? ?????????? ?if __name__=='__main__':?????????? ????test() |
另一种是创建?threading.Thread?的子类来包装一个线程对象。
?class timer(threading.Thread): # derived from the class threading.Thread?????def __init__(self,num,interval):?????????threading.Thread.__init__(self)?????????self.thread_num = num?????????self.interval = interval?????????self.thread_stop = False??????def run(self): #Overwrite run() method,put what you want the thread do here?????????while not self.thread_stop:?????????????print 'Thread Object(%d),Time:%s/n' %(self.thread_num,time.ctime())?????????????time.sleep(self.interval)???????def stop(self):????????self.thread_stop = True |
Python?线程中也提供同步机制,可以利用?thrading?模块的?threading.RLock?和?hreading.Condition?可以分别实现锁机制和条件变量。
其中?acquire()?和?release()?方法分别获取和释放锁。
????????? ?def run(self):?????????? ????????global x?????????? ????????lock.acquire()?????????? ????????for i in range(3):?????????? ????????????x = x + 1?????????? ????????time.sleep(2)?????????? ????????print x?????????? ????????lock.release() |
更多关于线程的内容,读者可查阅相关文档。
回页首
总结
本文从?Perl?和?Python?的起源,基本数据类型、控制结构、函数、包与模块、面向对象、正则表达式以及线程等方面进行了比较,从而给需要同时掌握这两种脚本语言的开发人员一定参考,以便更好的理解与应用。