一:解释性和编译型

梳理

编译型:源代码经过编译直接变为二进制的机器语言,每次都可以直接重新运行不需要翻译。典型的就是c语言。

解释性:java和python都是解释型,源代码经过编译变为字节码文件,然后将字节码放在VM上运行,达到跨平台的目的。

java和python都是边解释边执行,但是解释之前都先进行了编译工作,编译为vm能看懂的字节码,vm解释的是字节码,非源码和机器语言。

但是为什么python比java慢了一个级别?

主要原因是python是动态语言,java是静态语言。

静态语言:变量声明的时候要声明变量类型,这样编译器在程序运行时知道变量的类型。

动态语言:在程序运行时解释器只知道变量是一个对象,至于具体是什么类型解释器并不知道,所以每次程序运行的时候都要判断变量的类型,才能调用方法,以此来判断此变量对象有没有此方法。

还有像容器类型,java中的数组变量类型必须一致;但是python中list用的多,变量类型任意。

java对于相同类型,编译像预演一样,在现场直播时安排连续的一块小内存存放,寻址速度快

python则是全内存寻找变量,相比java肯定慢了。

正是因为动态语言多了一个类型判断的过程,因此python比java慢了一个级别。

动态语言是简单,但是解释器在背后做的事情比静态语言的解释器在背后做了更多的事情。

python两个概念,PyCodeObject和pyc文件

在硬盘上看到的pyc自然不必多说,而其实PyCodeObject则是Python编译器真正编译成的结果。

当python程序运行时,编译的结果保存在位于内存中的PyCodeObject中,当Python程序运行结束时,Python解释器则将PyCodeObject写回到pyc文件中,前提有写权限。

当python程序第二次运行时,首先程序会在硬盘中寻找pyc文件,如果找到对比修改时间,改动了就重新编译,没改动则直接载入,否则就重复上面的过程。

所以我们应该这样来定位PyCodeObject和pyc文件,我们说pyc文件其实是PyCodeObject的一种持久化保存方式。

test.py如下

def test():
print("Hello World")
if __name=="__main__":
test() 

此时python test.py发现硬盘中根本没有pyc文件

但是如果把函数定义放到另一个a.py文件中,在test.py中from a import test

此时再python test.py就会发现有了pyc文件。这说明了什么?

说明了pyc文件的目的是为了重用。

python解释器认为只有import的模块,才是要被重用的模块。对于test.py文件来讲,解释器不认为他是需要被重用的模块,因为他会被经常的改动,把它持久化是画蛇添足的,因为每次都要持久化为pyc文件,因此python只会把可重用的模块持久化为pyc文件。

速度

字节码并不能加快程序的运行速度,只是加快了代码的加载速度。

源代码都会被编译为字节码,java和Python都有这一步,当python运行主文件的时候,会将用到的其他模块全部编译为二进制的pyc文件来加快第二次运行程序时加载模块的速度,省去了源代码转为字节码的过程,解释器直接在pvm中拿到pyc文件直接执行。

当创建pyc文件的时候会和模块文件的最后一次修改时间进行映射,一旦第二次运行时会比较修改时间,如果修改时间没变就直接拿pyc文件执行,如果改变了就重新编译。

如果没有创建文件的权限,那么pyc文件是在内存存在的,每次运行pyc文件都是在内存重新编译生成,无法加快程序加载速度。

编译

java的编译就像预演一样,会把你所有的错误找出来,例如结果是none,然后你调用了一个方法,编译绝对无法通过。

python是没有预演,只有现场直播,根据表演者(程序员)的水平高低,经验少的就会在直播时出很多错误,经验丰富就会犯的错误少,同java一样对none对象调用方法,只有运行起来才会发现错误。

设计初衷

java的设计严谨,我认为有些过度设计,就像此次疫情中诞生的一个概念“去过度化”(2020年疫情期间修改)。

python崇尚鸭子类型和魔法方法(还有namespace),让python天生就是多态,不用像java刻意去多态,python内置的协议就是魔法方法,不同的魔法方法分别属于不同的大类

不再有接口的概念,尽管python用abc模块模仿了抽象类,但我几乎没怎么用过。

魔法方法就像是彩蛋一样,有各种被动的触发方式,任何一个类都可以将魔法方法放到里面来增强类的表达

python一切皆对象:元类type继承object类,元类type实例化了object类对象,听上去和现实是矛盾的,好像是一个闭环,但是在代码中并不矛盾,也是可以实现的。

矛盾是因为和现实世界映射对比起来矛盾:type继承了父类object,然后type又自己实例化了自己,然后又实例化了老爹,这什么玩意?

继承爹,又实例化爹在启动阶段并不矛盾,继承了静态的代码又没有调用爹的方法,开个后门让他过去

type类没用爹的方法,但是其他object类可能会使用object的方法,那没问题,只要其他对象在obejct实例化之后创建就可以了。

type继承object,object是对象,type也是对象;而type创建了所有的对象,那么一切都是对象。

type对象都是type自己创建的,用了一个指针而已。

python一切皆对象,1在java是基本数据类型,存放栈中,而pyhton一切皆对象,a=1背后是a=int(1),int是内置类,用的小写,1也是一个对象,在堆里面分配内存

堆空间比栈空间大的多,二者都去找1,当然java找的快。

总结

java和python程序速度差一个量级是因为语言本身的特性,静态和动态,与pyc文件毫无关系。

虽然速度差了一个量级,但是大多应用是无感知,0.1秒和0.01秒感觉都是过了1秒。

python是顺序执行代码的和if __name__=="__main__"无关。

一份程序为了区分主动执行还是被调用,Python引入了变量__name__,当文件是被调用时,__name__的值为模块名,当文件被执行时,__name__为'__main__'

1 #/usr/bin/env/ python            #(1) 起始行
2 #"this is a test module"      #(2) 模块文档(文档字符串)
3 import sys
4 import os              #(3) 模块导入
5
6 debug = True            #(4) (全局)变量定义
7 class FooClass (object):
8 'foo class'
9 pass #(5) 类定义(若有)
10 def main():
11 'test function'
12 foo = FooClass()
13 if debug:
14 print 'ran test()' #(6) 函数定义(若有)
15 if __name__ == '__main__':
16 main()

  

若是文件主动执行了,则最好写成跟上面的例子一样,main之前不要有可执行代码,这样做到程序从main()开始,流程逻辑性强

若是文件作为模块被调用,则可以不用写main(),从上而下顺序执行。

其实Python是否保存成pyc文件和我们在设计缓存系统时是一样的,我们可以仔细想想,到底什么是值得扔在缓存里的,什么是不值得扔在缓存里的。

在跑一个耗时的Python脚本时,我们如何能够稍微压榨一些程序的运行时间,就是将模块从主模块分开。(虽然往往这都不是瓶颈)

在设计一个软件系统时,重用和非重用的东西是不是也应该分开来对待,这是软件设计原则的重要部分。

在设计缓存系统(或者其他系统)时,我们如何来避免程序的过期,其实Python的解释器也为我们提供了一个特别常见而且有效的解决方案。

java和python对比的更多相关文章

  1. 对比java和python对比

    对比java和python 对比java和python 2011年04月18日 1.难易度而言.python远远简单于java. 2.开发速度.Python远优于java 3.运行速度.java远优于 ...

  2. java和python对比----实例化的对象属性:

    python 可以直接对实例化的属性进行赋值 class Test(): name = "小明" def __init__(self):{ //self.name = name; ...

  3. java和python对比----1:

    对计算来说: java 除法: 3/4 ==0; pyhton 除法: 3/4 ==0 3//4==0.75

  4. 对比JAVA、Python、C、Go运行时间,我惊呆了!!!

    对比JAVA.Python.C.Go运行时间,我惊呆了!!! 周末在寝室刷完算法,想放松一下,于是做了一个实验:用现在主流的几种编程语言对0 - (10000000 - 1)求和,结果我惊呆了,话不多 ...

  5. C#学习笔记(与Java、C、C++和Python对比)

    (搬运自我在SegmentFault的博客) 最近准备学习一下Unity3D,在C#和JavaScript中选择了C#.所以,作为学习Unity3D的准备工作,首先需要学习一下C#.用了一两天的时间学 ...

  6. Python和Java的语法对比,语法简洁上python的确完美胜出

    Python是一种广泛使用的解释型.高级编程.通用型编程语言,由吉多·范罗苏姆创造,第一版发布于1991年.可以视之为一种改良(加入一些其他编程语言的优点,如面向对象)的LISP.Python的设计哲 ...

  7. PHP、Java、Python、C、C++ 这几种编程语言都各有什么特点或优点

    PHP.Java.Python.C.C++ 这几种编程语言都各有什么特点或优点 汇编: C: Java: C#: PHP: Python: Go: Haskell: Lisp: C++: &l ...

  8. Java or Python?测试开发工程师如何选择合适的编程语言?

    很多测试开发工程师尤其是刚入行的同学对编程语言和技术栈选择问题特别关注,毕竟掌握一门编程语言要花不少时间成本,也直接关系到未来的面试和就业(不同企业/项目对技术栈要求也不一样),根据自身情况做一个相对 ...

  9. fasttext的基本使用 java 、python为例子

    fasttext的基本使用 java .python为例子 今天早上在地铁上看到知乎上看到有人使用fasttext进行文本分类,到公司试了下情况在GitHub上找了下,最开始是c++版本的实现,不过有 ...

随机推荐

  1. Python数据结构 - 利用headp模块寻找最大N个元素并实现优先队列

    用headp找到最大最小的N个值 import heapq nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] print(heapq.nlargest(3, ...

  2. 代理(Proxy)设计模式

    目录 概述 静态代理 UML类图 代码实现 代码地址 静态代理的不足 动态代理之jdk实现 UML类图 代码实现 利用JDK实现动态代理的优点 利用JDK实现动态代理的不足 代码地址 动态代理之cgl ...

  3. MapReduce与Yarn 的详细工作流程分析

    MapReduce详细工作流程之Map阶段 如上图所示 首先有一个200M的待处理文件 切片:在客户端提交之前,根据参数配置,进行任务规划,将文件按128M每块进行切片 提交:提交可以提交到本地工作环 ...

  4. Redis AOF 持久化详解

    Redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多.但是一旦进程退出,Redis 的数据就会丢失. 为了解决这个问题,Redis 提供了 RDB 和 ...

  5. JAVA的List接口的remove重载方法调用原理

    前言 说真的,平常看源码都是自己看完自己懂,很少有写出来的冲动. 但是在写算法的时候,经常用到java中各种集合,其中也比较常用到remove方法. remove有重载函数,分别传入参数是索引inde ...

  6. 【Tomcat】tomcat7 设置成系统服务启动

    1.启动cmd 2.cd C:\Program Files\tomcat7\bin 3.service.bat install 4.打开tomcat7w.exe可以启动管理服务

  7. redis系列之------简单的动态字符串(SDS)

    前言 Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串), 而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的 ...

  8. 重学Golang系列(一): 深入理解 interface和reflect

    前言 interface(即接口),是Go语言中一个重要的概念和知识点,而功能强大的reflect正是基于interface.本文即是对Go语言中的interface和reflect基础概念和用法的一 ...

  9. JavaScript设计模式——原型模式

    原型模式: 原型模式是指原型实例指向创建对象的种类,并通过拷贝这些原型创建新的对象,是一种用来创建对象的模式,也就是创建一个对象作为另一个对象的prototype属性: prototype警告:学习了 ...

  10. 关于django中input标签中file类型以及开路由

    0825自我总结 关于django中input标签中file类型 1.input提交图片实时展示 <img src="/static/img/default.png" wid ...