一、Perl 与 Python 的起源
Perl 是 Practical Extraction and Report Language 的简称,由 1987 年 Larry Wall 创建,最初的目的是为了在 UNIX 上方便处理报表,经过长期的发展已经成为一种全功能的程序设计语言,其中心思想是:There’s More Than One Way To Do It。Perl具有强大的正则表达式和模式匹配功能以及灵活的数据结构,但存在一些冗余语法,代码的可读性较差。
Python 是一种基于面向对象的解析性交互式的开源编程语言,它起源于 1989 年末由Guido van Rossum 创立,1991 年初公开发行。Python 开发者的哲学是“用一种方法,最好是只有一种方法来做一件事”。Python 具有简单易学、代码规范、语法简单、可移植性强、支持多平台、类库丰富等优点。
二、Perl 与 Python 的数据类型
Perl支持的基本数据类型包括:标量、数组、哈希。在定义的时分别用 $、@、% 表示。
- 标量 (scalar):大多数标量由数字或字符串组成。其中数字类型如整数、浮点数等,字符串有单引号和双引号内两种形式,对长度没有限制。两者的区别在于在单引号内
\n
不代表换行,而代表反斜线和 n 这两个字符,全部按照单引号内原样输出;双引号内字符串则可以通过反斜线进行转义。字符串的操作符有 . 拼接操作符和 x 重复操作符等。 - 数组 (Arrays):数组用 @ 定义,如
my @array=("a","b","c","d");
访问数组的元素用$array[1]
。
数组的操作包括pop
和push
,shft
和unshift
。pop
和push
对数组的尾部进行处理,而shift
和 unshift`则针对数组的头部进行处理。 - 哈希(Hash):是根据关键码值 (Key value) 而直接进行访问的数据结构。用
%
定义,如%my_hash=(“key1”=>”23”,”name”=>”zhang”,”age”=>”21”)
,其中键以字符串表示,Hash 可以是任意大小。
相关的函数有:
keys:返回 hash 的键列表my @keylist = keys %hash
value:返回值列表my @valuelist = values %hash
each:用两个元素的列表返回键值对。
while(($key,$value)= each %hash) { print “$key =>$value\n”; }
Python 支持五种基本数据类型:数字 (Numbers)、字符串 (String)、列表 (List)、元组 (Tuple) 和字典 (Dictionary)。其中数字和字符串和 perl 中的标量对应,列表和数组对应,元组可以看做是不可变的列表,字典和 hash 对应。
- 数字 (Numbers):Python 支持五种基本数字类型,分别为 int( 有符号整数 ) 、long( 长整数 ) 、bool( 布尔值 ) 、float( 浮点数 ) 、complex( 复数 )。
- 字符串 (String):Python 与 Perl 一样也支持单引号和双引号字符串,但与 Perl 不同,转义字符在单引号中也会起作用。
字符串支持操作符in
,not in
,连接操作符+
以及重复操作符*
。Python 字符串可以当做 list,支持切片操作符[]
,[:]
和反向索引。如aString=”abcd”
;则aString[0]
的值为 a,aString[1:3]=bc
,反向索引aString[-1]=d
- 列表 (List):Pyhon 中的列表与 Perl 中的数组相对应。列表的定义使用
[]
. 如lis = ["a", "b", "mpilgrim", "z", "example"]
,支持动态增加和删除元素以及切片操作。
增加元素可以使用lis.append(“test”)
,lis.insert(2,”new”)
以及lis.extend([“f”,”ggf”])
删除元素使用lis.remove(“f”)
和lis.pop()
。但需要注意的是 remove 仅删除首次出现的,而 pop 会删除 list 最后的一个元素,然后返回删除的元素的值。 - 元组 (Tuple):元组和列表非常相似,但用()表示,并且元组是不可变的。
- 字典 (Dictionary):字典跟 Perl 中的 hash 一样,定义了键值对之间一对一的关系,变量可以任意取名,Python 会在内部记录其数据类型。定义一个字典:
D={“name”:”Jon”,”Family”:”SH”}
, 字典中的 key 是不能重复的,并且大小写敏感,同时字典中的元素是无序的。
字典也支持增删操作,往字典中添加元素D[“age”]=23
, 删除元素del D['name']
,如果需要删除所有元素可以使用D.clear()
, 或者del D
删除整个字典。
三、Perl 与 Python 的控制流
3.1 If/unless 控制结构
Perl 与 Python 都支持 if 、if-else 、if-else if- else 三种结构,两者在语法上基本类似,但与 Python 不同的是 Perl 中没有 boolean 类型,零和空表示 False,其余表示 True,而 Python 中除了’’、""、0、()、[]、{}、None 为 False 之外,其他的都是 True。同时 Python 直接用缩进表示 block 块。
- Markdown的表格显示不是很方便展示py的空格55,这边只能凑合一下啦
Perl | Python | |
---|---|---|
if | if (expression) {true_statement;} | if expression: if_suite |
if-else | if (expression) {true_statement;} else{else_suite} | 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 语句。
3.2 循环控制结构
3.2.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
3.2.2 while 循环
**Perl **循环控制结果支持 while 和 do-while 以及 until 形式,until 与 while 结构相似,区别在于 unitl 会在条件为假的时候重复执行。until 语法如下:
until(expression)
{
statement;
}
而 python 只支持 while 形式,但 python 可以在 while 后面接 else 语句。语法如下:
While condition:
statements
else:
statements
3.2.3 循环控制符
Perl 有三个循环控制操作符,分别为 Last 、next 、redo。
- last:立即终止循环,类似于 c 中的 break。在多层循环中,只对 last 所在的当前循环块有效;
- next:立刻结束当前这次迭代;
- redo:将控制返回本循环的顶端,不经过条件测试也不会进去下一次迭代循环,而是重新执行本循环块。它与 next 最大的区别在于 next 会正常继续下一次迭代,而 redo 会重新执行本次迭代。
Python 也有三个循环控制操作符,分别为 break 、continue 、pass 语句。
- break:与 C 中的 break 类似;
- continue:continue 语句并不会退出循环结构,而是立即结束本次循环,重新开始下一轮循环,也就是说,跳过循环体中在 continue 语句之后的所有语句,继续下一轮循环;
- pass:一般作为占位符或者创建占位程序,pass 语句不会执行任何操作。
四、Perl 与 Python 的I/O
Perl:
获取用户命令行输入:$input=<STDIN>
@ARGV
命令行输入的东西,按空格分开,一次存入数组
输出:print STDOUT
Python:
message = input("Tell me something,and I will repeat it back to you: ")
将获取内容存储为字符串;
冒号后面,包含一个空格,可将提示与用户输入分开,让用户清楚的知道其输入始于何处
print(message)
message = int(message)
如果message获取的内容是数值,则可以用int()转为数值
五、Perl 与 Python 的包与模块
Perl 程序把变量和子程序的名称存贮到符号表中,Perl 的符号表中名字的集合就称为 Perl 包 (package)。
- 定义语法为:package mypack;每个符号表有其自己的一组变量、子程序名,各组名字是不相关的,因此可以在不同的 Perl 包中使用相同的变量名,而代表的是不同的变量。
- Perl 模块有两种来源,一种是随 Perl 发行版本一同打包的,另外就是用 CPAN 中下载的。Perl 模块和包的概念并不清晰,两者有时可以混用。
- 导入模块关键字
use
;如:use ModuleName
;模块被导入后,其中的子程序和变量就可以直接使用了;要取消一个已经导入了的模块,可以使用关键字no
;如:no ModuleName
Python:一个 .py 文件就是一个 python 模块。把一堆相关的 python 模块放在一个目录下,再加上一个 init.py 文件就构成了一个 python 包。
在 Python 另一个程序中导入模块用 import module
或者 from module import *
,两者的区别在于:import module
会导入 module 这个模块里的所有标识,但是这些标识现在都在 module 名字空间下。from module import *
也会导入 module 中所有标识,但是标识放到在当前名字空间里。
六、Perl 与 Python 的函数
Perl | Python | |
---|---|---|
定义 | 基本语法: sub functionName{ statement; [return value] } | 基本语法: def functionName(arg1,arg2,[…]): statement [return value] |
返回值 | 使用 return 语句显示返回;如果没有 return,默认返回最后一次运算的结果 | 使用 return 语句显示返回,没有 return 语句,默认返回为 None。如果函数返回多个对象,python 把他们聚集起来并以一个元组返回。 |
调用 | & 函数名(参数 1,参数 2,…),如果声明在前,可以省略 &。如果用户所定义的子过程与内置函数重名,则不能省略 &。 | 直接采用 函数名(参数 1,参数 2…) 函数名(参数名 1= 值,参数名 2= 值 …) |
函数参数 | 1. 在子程序调用的后面加上被括号圈引的列表表达式即可,所有的参数都会自动存储为 @_ 中,其中第一个参数为 $[0], 第二个参数存储 $[1]。 2. 传递引用,在参数前加入 \ 表示为引用 | 1. 按照参数声明的关键字顺序直接传递; 2. 通过关键字参数 testFun(par1=“2”,par2=“45”) 3. 默认参数 4. 变长参数:利用非关键字可变长参数 , 可变长的参数元组必须在位置和默认参数之后 |
七、Perl 与 Python 的正则表达式
perl 中正则表达式有三种形式:
- 匹配:m// (还可以简写为 /;/ ,略去 m)
- 替换:s/// ,为了语法的简化用 /// 表示,略去 s
- 转换:tr/// 这种形式包含一系列的字符— / —同时把它们替换为 。
Python
Python 本身不支持正则表达式,依赖 re 模块。
有搜索和匹配两种方法完成匹配模式。re 模块常用的函数和方法有 complie、match、search、find 与 findall 等。在利用 re 进行匹配之前,模式必须被编译成 regex 对象。
八、Perl 与 Python 中的线程
Perl 中一个线程的生命周期包括创建,运行与退出这三个阶段。线程的运行过程与普通函数的执行类似,但新建线程的执行与当前线程的执行是并行的。
在 Perl 中创建线程有两种方法:
- 使用 threads 包的 create() 方法
use threads;
sub say_hello
{
printf("Hello thread! @_.\n");
return( rand(10) );
}
my $t1 = threads->create( \&say_hello, "param1", "param2" );
- 使用 async{} 块创建线程
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() 函数来产生新线程。另一种是创建 threading.Thread 的子类来包装一个线程对象。
九、总结
以上从 Perl 和 Python 的起源,基本数据类型、控制结构、I/O、包与模块、函数、正则表达式以及线程方面进行了比较,当然perl和python的区别远不止于此,还需要在实践中自行体会~