作为万年Perl 党表示最近开始学Python 了,下面会记录一下学习中Python 和Perl 的对比,如果你也是一个Perl 用户,看过了也会对Python 有一个大致的印象吧。

事实上,写着写着我发现如果你是一名Python 用户,看完后也会对Perl 有一个大致的了解 _(:з)∠)_

基本数据类型1. Perl 中的标量

a. Perl 中的标量在Python 中对应为数字类型和字符串类型

Perl 的标量是字符串还是数值会根据上下文自动判断,但是Python 不会这样做。

下面的代码是你在Perl 中习以为常的操作

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my ($string, $number) = ("1", );

$number= $string + "1"; # $string 和"1"都被解释为数值

say $number;

$string = $number.1; # $number 和1 都被解释为字符串

say $string;

但是Python 中你必须显式的指定数据类型

[python] view plaincopy在CODE上查看代码片派生到我的代码片string = "1"number= int (string) + 1# 必须显式转换为数值类型

print (number)string = str (number) + "1"# 同样必须显式转换为字符串

print (string)

b. Perl 的标量不支持下标运算,但是Python 的字符串可以

Python 中你可以很方便的用下标索引字符串(而且和Perl 中的列表一样也支持用负数做反向索引)

[python] view plaincopy在CODE上查看代码片派生到我的代码片

s= "A string"print (s[2:])

但是Perl 的标量就无法这样操作,相同的操作必须用列表切片完成

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

$_= "A string";

say ((split//)[2..split//]);

c. Perl 中的heredoc 式标量赋值在Python 中可以使用三引号运算符完成

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

@_=

inthe array

END

say"@_";

下面是等价的Python 代码,注意第一行是紧跟三引号运算符之后的

[python] view plaincopy在CODE上查看代码片派生到我的代码片string = '''''Everthing is

inthe array'''

print (string)2. Perl 中的列表

a. Perl 中的列表Python 中对应为列表和元组

下面是Python 中倒序排序一个列表的操作

[python] view plaincopy在CODE上查看代码片派生到我的代码片

my_list= ["Hello", "Python"]

my_list.append ("World")

my_list+= ["!"]

print (my_list)

my_list.sort ();

my_list.reverse ();for string inmy_list:

print (string)

对应的Perl 同性质操作的版本

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

@_= qw/Hello Perl/;

push @_,'World';

@_= (@_, '!');

print"@_\n";

@_=reverse sort @_;

sayfor@_;

b. 常用的splice 操作在Python 中可以用过index () 方法和del 操作完成

下面是Perl 中常用的splice 操作

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

@_= qw/Hello Perl !/;

splice @_,2, 0, "World"; # 插入元素

say"@_";

my @removed= splice @_, 1, 2; # 提取一段元素并在原列表删除

print"@_\n@removed\n";

Python 中对应的操作

[python] view plaincopy在CODE上查看代码片派生到我的代码片

my_list= ["Hello", "Python", "!"]

my_list.insert (2, "World") # 插入元素

print (my_list)

removed= my_list[1:2] # 提取一段元素

del my_list[1:2] # 并在原列表删除

print (my_list)

print (removed)

注意:Python 中元组和列表的区别

元组创建后是只读的,但是列表随时都可以被修改。3. Perl 中的哈希

a. Perl 中的哈希Python 中对应为字典和集合

一个Perl 哈希按照键值升序遍历的操作如下

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my%hash =("first" => 1,"second" => 2,"third" => 3);

say"$_ => $hash{$_}" for sort keys %hash;

Python 中代码如下(注意定义变为花括号)

[python] view plaincopy在CODE上查看代码片派生到我的代码片

my_hash={"first" : 1,"second" : 2,"third" : 3}

items= sorted (my_hash.items (), key=lambda e:e[1], reverse=False)for item initems:

print (item[0], ':', item[1])

注意:Python 中集合与字典的不同之处

(a) 仅包含键,但是没有值

(b)set可变,但是frozenset 不可变(如其名)4. Python 强类型的判断和赋值

一个非常大的不同之处:Perl 中赋值号默认的行为是拷贝,但是Python 中赋值号会创建一个对象的引用。

另外,因为和弱类型的Perl 不同,Python 是一门强类型语言,所以也有判断对象类型的必要。

下面代码演示了这些区别,首先是一段Python 代码

[python] view plaincopy在CODE上查看代码片派生到我的代码片

lst= [1, 2, 3]

lst2=lst # lst2 是lst 的一个引用

print (lst)

lst2[1] = 2.5# 所以修改lst2 也会引起lst 的变化

print (lst)

lst3=copy.deepcopy (lst) # lst3 是lst 的一个深拷贝

lst3[1] = 2print (lst) # 修改lst3 不会引起lst 的变化

# 因为Python 是强类型语言,所以需要类型判断操作if lst ==lst2: # 如果s 和s2 值相同

print ("lst equal to lst2")if lst islst2: # 如果s 和s2 是指向同一个对象的引用

print ("lst and lst2 is the same")if type (lst) istype (lst3): # 如果s 和s3 类型相同

print ("lst and lst3 has same type")

下面是与之完全等价的Perl 代码,对比一下你就会很快了解其中的差别

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my @lst= (1..3);

my $lst2=\@lst; # lst2 是lst 的一个引用

say"@$lst2";

$lst2->[1] = 2.5; # 所以修改lst2 也会引起lst 的变化

say"@$lst2";

my @lst3=@lst; # lst3 是lst 的一个深拷贝

$lst3[1] = 2;

say"@lst"; # 修改lst3 不会引起lst 的变化=pod

因为Perl 是弱类型语言,所以不需要类型判断操作

但是Perl 中仍然可以做这样的操作——虽然没什么意义=cut

say"lst equal to lst2"

if @lst ==@$lst2; # 如果s 和s2 值相同

say"lst and lst2 is the same"

if \@lst ==$lst2; # 如果s 和s2 是指向同一个对象的引用

say"lst and lst3 has same type"

if ref \@lst eq ref\@lst3; # 如果s 和s3 类型相同5. Perl 中的“上下文”

上下文的判断几乎已经成了一名Perl 用户不可或缺的第六感,一个显而易见的例子是当你定义一个列表

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my @lst= (1..3);

当你循环遍历的时候,你深知把for 循环

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

sayfor@lst; # 列表上下文

替换为While 循环

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

saywhile@lst; # 标量上下文

究竟会得到什么灾难性的后果。

但是在Python 中你不必担心这个:Python 对于数据类型的解释很明确,不会因为上下文环境不同而改变,当你定义一个列表

[python] view plaincopy在CODE上查看代码片派生到我的代码片

lst= [1, 2, 3]

之后,你永远不必担心在什么特殊的上下文中lst 会被Python 解释为数值3。

面向对象编程1. 几点明显的异同

Perl 和Python 的面向对象给人的感觉是后者明显比前者更加规范,下面是自己感受最明显的几点异同。

a. 真的是面向对象么?1). Perl 中的“面向对象”更像是“面向过程”的文字游戏:类通过包实现、方法通过包中定义的函数实现、类的继承和方法的重载通过@ISA 列表查找循序实现、私有方法通过指向匿名函数的my 引用实现(因为my变量是本文件可见的)、运算符重载通过指向函数的引用实现、对象中成员变量的访问通过bless 到类名的引用实现……这样如果说有好处,那就是编程可以非常灵活——你可以用一个父类的多个子类共同继承出一个类(例如从哺乳动物中人类和猫类继承出一种新生物),Perl 完全对这种行为不在意,只要你确信这种近亲结婚的方式真的是你需要达到的目的。当然坏处显而易见——你可以轻而易举把代码写的糟糕透顶。所以Perl 的“面向对象”给人的感觉只是“面向过程”的另一种玩法——面向过程的本质没变,但是面向对象的效果达到了。2). Python 中的“面向对象”比Perl 要严谨和规范许多,非常类似于Java,如果你熟悉Java 或者C++,那么你会很好理解Python 的面向对象编程。

b. 包和类1). Perl 中两者完全等价,一个包就是一个类(pm 是Perl 模块的意思,但是它又被叫做包,而包就是类的意思 ← ←)。2). Python 中一个包可以包含多个模块,一个模块可以包含多个类。

c. 静态方法

Perl 和Python 中静态方法都是第一个参数不是类的引用的方法,但是稍有不同:1). Perl 中静态方法第一个参数是类名,可以通过bless 新的引用到类名来操作对象类型(例如你在构造方法里做的那样)。2). Python 中静态方法完全无法操作对象类型。

d. 私有方法:1). Perl 中的私有方法通过my 变量只有当前文件可见的性质,用保存匿名函数的my 引用来达到“私有”的目的(“面向对象”的文字游戏)。2). Python 中吧以“__”开头的方法都当作私有方法,通过方法名会变成"_类名__方法名"的形式来避免其他类调用该方法,但是你仍然可以通过手动变换后的方法名直接调用私有方法。

e. 方法的传参:1). Perl 中一般将散列的引用bless 到类名,所以传参可以十分灵活,如果构造函数允许,参数个数和位置根本无关紧要,但是随之造成的问题就是可能引发混乱。2). Python 中方法声明无法把无默认值的参数放在有默认值的参数后面,但是因为实参可以通过给出参数名手动显式指定,所以次序也可以无关紧要。

f. 运算符重载:1). Perl 通过use overload 模块指定方法的引用来达到重载运算符的目的。2). Python 中通过一组特殊名称的方法来重载运算符。

g. 父类方法重载:1). Perl 中通过@ISA 列表的搜索顺序来达到重载父类方法的目的(子类的同名方法会被优先搜索到),并且可以显式SUPER 伪类访问被覆盖的基类方法(就如你经常在析构方法中做的一样)。2). Python 的重载更加正式,形式非常类似于C++。

h. 继承:1). Perl 的继承只是操作了@ISA 列表,子类中没有的方法会在@ISA 中寻找方法名,因此这种行为得到的结果和面向对象编程的继承相同。UNIVERSAL 是所有类的祖先类,提供了isa 方法用来测试继承关系。2). Python 的继承类似于C++,显式指定了要继承的父类,object类是所有类的祖先类,提供issubclass 方法用来测试继承关系。2. 一个演示异同的例子

下面的两个例子都会有相同的输出,演示了Perl 和Python 中类的构造、析构、公有方法、私有方法、运算符重载、继承、父类方法重载等。

下面是预期的输出

[plain] view plaincopy在CODE上查看代码片派生到我的代码片=My name's Lucy, 2 years old. Adoption me please.

+I am hungry offen.-My name's Leia, 1 years old. My host is iSpeller.

+I hate milk but my host give me offen.-My name's Lucy, 2 years old. My host is iSpeller.

+I hate milk but my host give me offen.--------------------------------------------------------下面是你熟悉的Perl

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

#!/usr/bin/perl

#========================# filename: main.pm

# main 类,演示了:

# 类的实例化

#=======================package main;

use warnings;

use strict;

use5.010;

use Dog;

use Pet_Dog;

push @INC,'.';

# 一条叫Lucy 的汪星人

my $lucy= Dog->new (name => 'Lucy', age => 2);

$lucy->say_hello;

$lucy->my_secret;

# 第一条宠物汪,默认为1 岁的leia

my $pet_leia= Pet_Dog->new (host => 'iSpeller');

$pet_leia->say_hello;

$pet_leia->my_secret;

# 纳入第二个宠物汪

# 调用了Pet 类运算符重载函数

my $pet_lucy= $lucy + "iSpeller";

$pet_lucy->say_hello;

$pet_lucy->my_secret;1;

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

#========================# filename: Dog.pm

# Pet 类,演示了:

# 构造、析构方法

# 公有、私有方法

# 重载

#========================package Dog;

use strict;

use warnings;

use5.010;

use overload'+' => \&meet; # 重载加号运算符

# 构造方法

# 是静态方法,第一个参数为类名

subnew{

my $type=shift;

my $class = ref $type ||$type;

# 如有用户实例变量则覆盖默认属性

my $self= { name => 'Leia', age => 1, is_pet => 0, @_ };

bless $self, $class;return$self;

}

# 析构方法

# 是虚方法,第一个参数为类的引用

sub DESTROY {

my $self=shift;

# 调用父类析构方法

$self->SUPER::DESTROYif $self->can ('SUPER::DESTROY');

}

# 公有方法

sub say_hello {

my $self=shift;

print'='

if $self->isa ("UNIVERSAL"); # UNIVERSAL 类是所有类的祖先类

printf"My name's %s, %d years old. %s.\n",

$self->{name}, $self->{age},

$self->{is_pet}? "I am a pet dot":"Adoption me please";

}

# 私有方法

my $say_secret=sub {

my $self=shift;

say'+', $self->{is_pet}? "I hate milk but my host give me offen.":"I am hungry offen.";

};

# 私有方法只能在本文件内由其他方法访问(my $say_secret)

sub my_secret {

my $self=shift;

$self->$say_secret;

}

# 重载加号运算符,返回成为宠物后的自身

sub meet {

my $self=shift;

my @property= %$self;

my $new = Pet_Dog->new (@property, host =>shift);return $new;

}1;

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

#========================# filename: Pet_Dog.pm

# Pet_Dog 类,继承自Dog 类,演示了:

# 继承、父类方法的重载

#=======================package Pet_Dog;

use strict;

use warnings;

use5.010;

usebase qw/Dog/; # 继承自Dog 类

subnew{

# 调用父类的构造方法

# 因为shift 得到的是子类的类名,所以不需要重新bless

my $self= Dog::new (shift, host => "none", @_, is_pet => 1);return$self;

}

# 重载父类的say_hello (虚)方法

sub say_hello {

my $self=shift;

print'-'

if $self->isa ("Dog"); # 继承关系测试

printf"My name's %s, %d years old. My host is %s.\n",

$self->{name}, $self->{age}, $self->{host};

}1;--------------------------------------------------------下面是完全等价的Python

[python] view plaincopy在CODE上查看代码片派生到我的代码片

#!/usr/bin/python3

# filename: main.py

#========================# Dog 类,演示了:

# 构造、析构方法

# 公有、私有方法

# 重载

#========================

classDog:

# 构造方法

# 是私有方法,因为方法名以"__"开头

def __init__ (self, name= "Leia", age = 1, is_pet = 0):

# 如有用户实例变量则覆盖默认属性

self.name=name

self.age=age

self.is_pet=is_pet

# 析构方法

# 静态方法,不会操作实例类型

# 类似Perl,第一个参数不是引用,所以你无法通过第一个参数来引用实例变量

@staticmethod

def __del__ ():

pass

# 公有方法

def say_hello (self):if issubclass (Dog, object):

print ("=", end='')

print ("My name's %s, %d years old. %s."

%(self.name, self.age,

# Python 中没有三目运算符,可以用下面的形式替代"I am a pet dog"

ifself.is_petelse "Adoption me please"))

# 私有方法

def __say_secret (self):

print ("+%s."

% ("I hate milk but my host give me offen"

ifself.is_petelse "I am hungry offen"))

# 私有方法只能在本类内由其他方法访问

def my_secret (self):

self.__say_secret ()

# 重载加号运算符为和对方恋爱,返回成为女朋友后的自身

def __add__ (self, other):new = Pet_Dog (self.name, self.age, 1, other)return (new)

#========================# Pet_Dog 类,继承自Dog 类,演示了:

# 继承、父类方法的重载

#========================

classPet_Dog (Dog):

# 调用父类的构造方法

# 之后初始化子类变量

def __init__ (self, name= "Leia", age = 1, is_pet = 1, host = "none"):

Dog.__init__ (self, name, age, is_pet)

self.host=host

# 重载父类的say_hello (虚)方法

def say_hello (self):ifissubclass (Pet_Dog, Dog):

print ("-", end='')

print ("My name's %s, %d years old. My host is %s."

%(self.name, self.age, self.host))'''''

程序开始,Python 的类型不允许在定义之前使用

然而Python 似乎又不区分声明和定义

演示了类的实例化'''

# 一条叫Lucy 的汪星人

lucy= Dog ("Lucy", 2)

lucy.say_hello ()

lucy.my_secret ()

# 第一条宠物汪,默认为1 岁的leia

pet_dog_leia= Pet_Dog (host = "iSpeller");

pet_dog_leia.say_hello ()

pet_dog_leia.my_secret ()

# 纳入第二宠物汪

# 调用了Pet 类运算符重载函数

pet_dog_lucy= lucy + "iSpeller"pet_dog_lucy.say_hello ()

pet_dog_lucy.my_secret ()

转载自:http://blog.csdn.net/iSpeller/article/details/23198211

python和perl语言的区别_Perl 和 Python 的比较 【转】相关推荐

  1. 谈谈对python 和其他语言的区别_谈谈Python和其他语言的区别

    Python属于解释型语言,当程序运行时,是一行一行的解释,并运行,所以调式代码很方便,开发效率高, 还有龟叔给Python定位是任其自由发展.优雅.明确.简单,所以在每个领域都有建树,所有它有着非常 ...

  2. Python和Go语言的区别

    Python和Go语言的区别 什么是Python? Python是一种功能强大的高级编程语言,主要用于科学和工程计算.它是一种高效的语言,优雅务实,简单而强大,适合新手和专业人士的编程. Python ...

  3. python和c语言的区别有哪些

    python和c语言的区别有哪些 Python可以说是目前最火的语言之一了,人工智能的兴起让Python一夜之间变得家喻户晓,Python号称目前最最简单易学的语言,现在有不少高校开始将Python作 ...

  4. 【Python面试】谈谈对 Python 和其他语言的区别?​

    最近公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开 ...

  5. python和c语言的区别-c语言和python的区别是什么

    python和C语言的区别如下: 1.C语言是编译语言,Python是脚本语言.说是C语言会比Python快 (看了看学校oj最简单的A+B问题,C语言的运行事件大致在0ms,而Python是6.7. ...

  6. python和c 的区别-Python与C语言的区别

    作为目前最火爆的语言之一,人工智能的兴起让Python一夜之间家喻户晓,几乎所有人对于Python的理解都是"简单""易学",甚至不少中小学也开始计划将Pyth ...

  7. r与python的区别和联系-Python和R语言的区别?

    Python和R语言的区别 Python和R语言的 数据挖掘技术日趋成熟和,随着互联网以及大批海量数据来,之前传统的依靠spss.SAS等可视化工具实现数据挖掘建模已经越来越不能满足日常需求,依据美国 ...

  8. 芯片验证学perl还是python_科学网—用python或perl语言简单验证RSA算法 - 康建的博文...

    python或perl语言都提供了很方便的对大整数计算的功能,这在C或Fortran中不易实现,需调用相关的库或另编程序. 多年前听公开课,一位老师给学生讲电子商务安全,涉及到公钥密码,讲得生动,但没 ...

  9. 谈谈对 Python 和其他语言的区别

    Python 爬虫面试题 170 道:2019 版 语言特性 谈谈对 Python 和其他语言的区别: 语言特点:简洁.优雅,省略了各种大括号和分号,还有一些关键字,类型说明: 语言类型:解释型语言, ...

最新文章

  1. C++11中值得关注的几大变化 .
  2. ARP***绑定 linux/windows 下解决方案
  3. 虚拟存储器管理(C++实现)
  4. 共享计算机后无法访问磁盘,win10电脑共享硬盘无法访问如何解决
  5. C语言指针操作字符数组demo
  6. [转]Artech的WCF之旅(1):创建一个简单的WCF程序
  7. RXTX for java在arm上的使用
  8. 微信小程序点击文字变色
  9. 营收环比增幅近50%,星巴克在经历“劫”后重生吗?
  10. 解决Win10系统过期失效问题的经验总结
  11. java卸载错误2503_修复控制面板卸载程序时提示错误代码2502、2503的方法
  12. 今日分享:如何获取接口(Charles、fiddler)
  13. oracle数据库中小数小于1时0不显示
  14. 法国队夺了世界杯冠军,却彻底打了AI预测的脸
  15. 职场情商训练 - 下属的工作技巧
  16. Leetcode 590: N-ary树的后序遍历
  17. 第十三周完成情况 学生选课管理系统 王杰 孙乾 蔚晓青
  18. debian linux镜像下载,Debian Wheezy 7.7 发布,已提供镜像下载更新
  19. 阿里五年老将的创业故事
  20. 4, excel vba 往单元格里写入数据

热门文章

  1. 九月英语——梦开始的地方
  2. 一家之言:谈谈JavaScript匿名函数(转)
  3. 帆软报表获取管理平台用户信息
  4. 长在不同部位逗逗的情况
  5. 轮胎侧偏角、侧向力分析说明
  6. 计算机网络:数据链路层之虚拟局域网,高速以太网
  7. 8800DF020SK3N1D1E3M5艾默生涡街流量计
  8. 嫁给玩股票男人的九大理由
  9. linux运行界别,day7 Linux下必知必会文件(2)
  10. CDGP|保险行业如何做好数据治理?