文章标题

Why Python

本文默认有一定java基础或者深入理解java更好,首次在工作中接触python的第一个疑问就是,为什么用python,和java对比如何?

两种语言核心对比点是:

对比项目JAVAPYTHON总结
语言类型(对变量的处理方式)静态类型:一旦声明类型,不可动态更改动态类型:不必声明类型,python根据运行时的值进行类型指定,同样可以string替换一个integer。关于静态类型和动态类型相关的争论已经持续很久了,有一个比较有意思的谈话是关于 Guido van Rossum关于Python运行时、类型方面的思考 Strong versus Weak Typing。主要讨论还是集中在开发效率、运行效率和企业级应用的构建上。Python胜在原型构建速度上,java胜在运行效率和企业级应用上。
原型构建速度和系统运行效率Java运行效率更高Python的产品构架你速度更高在许多研究结论中都可以得出一个结论:Python比Java的生产效率高出两倍。(1)Python为什么会比Java构建效率高可以深入参考Python速度虽然慢,但它工作效率高啊。(2)Python运行效率为什么低,有篇好文分析的很深入why python is slow
JVM(HotSpot)和Python解释(CPython)Java现阶段比较流行的虚拟机是HotSpot(包括了一个解释器和两个编译器)Cpython解释器是实现python的其中的一个版本,也是现在官方的、最流行的版本Java和Python的实现都依托于各自的解释器和编译器。JVM虚拟机有自己很完善的架构并且在运行前进行编译成Bytecode并在运行时解释成机器语言。Cpython是在运行期间将Python解释成机器语言在效率上要慢一些

在Python支持者的观点中有一点非常好:要准确的定位到自身产品和系统的瓶颈。如今的计算机和网络,在系统的前期甚至是中后期,运行效率和伸缩复用性一般都不会成为系统的瓶颈,往往业务上的速度至关重要。

Python 安装

Python & Java Side by Side基础

输出和运行

  • Java

    public class HelloWorld {
      public static void main(String[] args) {
          System.out.println("Hello World");
      } 
    }
    
    运行:javac HelloWorld.java
       java HelloWorld
  • Python

    print 'Hello World'
    
    运行:python HelloWorld.python

变量(数值,字符,列表,字典)和赋值

  • Java

    Java是静态类型语言,必须制定变量类型

    Integer a = 10;
    String b = "abc";
    List<String> c = Arrays.asList(1,2,3,4);
    Map<String, String> d = new HashMap<>();
    d.put("key","value");
  • Python

    Python是动态类型语言,动态类型语言,运行期间制定类型

    a = 10
    b = "abc"
    c = [1, 2, 3, 4]
    d = {'key': 'value', 'key1': 'value1'}
    
    print type(a)
    print type(b)
    print type(c)
    print type(d)
    
    输出:<type 'int'>
    <type 'str'>
    <type 'list'>
    <type 'dict'>

代码块(if条件实例)

  • Java

    Java中if、class、while、for、方法等都是通过“{}”大括号进行开始和结尾的,进行代码块区分

    if (a == b) {
      System.out.println("a equals b");
    } else if (a > b){
      System.out.println("a is bigger");
    } else {
      System.out.println("b is bigger");
    }
  • Python

    Python中的if、class、def(方法)、for等这样的复合语句以关键字开始,冒号结束。同时通过4个空格进行缩紧区分代码块

    if a == b:
      print "a equals b"
    elif a > b:
      print "a is bigger"
    else:
      print "b is bigger"

循环

  • Java

    for (Integer one : a) {
    System.out.println(a);
    }
    for (Map.Entry<String, String> entry : b.entrySet()) {
    System.out.println(entry.getKey());
    }
  • Python

    for one in c:
      print one
    
    for one in d:
      print one

文件操作

  • Java

    File file = new File(filePath);
    InputStream in = null;
    try {
      System.out.println("以字节为单位读取文件内容,一次读一个字节:");
      // 一次读一个字节
      in = new FileInputStream(file);
      int tempbyte;
      while ((tempbyte = in.read()) != -1) {
          System.out.write(tempbyte);
      }
      in.close();
    } catch (IOException e) {
      e.printStackTrace();
      return;
    }
  • Python


    myFile = open(filePath)
    print myFile.read()

函数

  • Java

    public static Integer functionName(Integer a, Integer b) {
      return a + b;   
    }
    
    public static void main(String[] args) {
      functionName(1, 2)
    }
  • Python

    python方法的命名以下划线分割

    def function_name(code=None, type=None):
      return code + type
    
    if __name__ == '__main__':
      r = function_name(code = 1, type = 2)
      print r

  • Java

    public class MyClass {
      public Integer functionName(Integer a, Integer b) {
        return a + b;   
    }
    
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.functionName(1, 2);
    }
    }
  • Python

    python并不像Java一样强制面向对象创建类,可以不进行类的创建

    class MyClass(object):
      def __init__(self, code=None):
          self.code = code
          print 'created a instance'
    
      def show_code(self):
          print self.code
    
    if __name__ == '__main__':
      my_class = MyClass(1)
      my_class.show_code()
    

模块

  • python

    python中的模块是将代码分成有组织的代码段,一个文件可以被看成一个独立的模块。模块的文件名就是模块的名字加上扩展名.py

    >>> import mymoudle
    输出:
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    ImportError: No module named mymoudle

    python查找模块的路径

    >>> import sys
    >>> sys.path
    
    输出:
    ['', '/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload', '/Library/Python/2.7/site-packages', '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python', '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC']

    以上输出结果就是python默认查找模块的地址,可以把自己的mymoudle放到当前目录就可以进行import

    mymoudle.py
    
    def sum(a, b):
      print a + b
    
    >>> import mymoudle
    >>> mymoudle.my_sum(1, 2)
    3

标准类型分类

Python标准类型可以分为:数值、字符串、列表、元组合字典

  • 按照存储模型分类(能存储多少对象)
分类Python 类型
原子类型数值、字符串
容器类型列表、元组、字典

* 按照更新类型分类(对象创建后它的值是否可以改变)

分类Python 类型
不可变类型数值、字符串
可变类型列表、元组、字典

“`

a = 1
id(a)
140718964233288
a = 2
id(a)
140718964233264
str = ‘xxxx’
id(str)
4459015312
str = ‘aaaa’
id(str)
4459015504

既然a可以被重新赋值,那为什么说是不可变类型。原因就像输出一样,实际是新创建了一个对象,而不是修改原有对象的值
“`

“`

alist = [1, 2, 3]
alist[2]
3
id(alist)
4458858400
alist[2] = alist[2] + 1
alist
[1, 2, 4]
id(alist)
4458858400

对象的值可以进行修改
“`

“`

a=256
b=256
id(a)
140718964239024
id(b)
140718964239024
a=257
b=257
id(a)
140718964266976
id(b)
140718964267072

Python和Java一样会对常用的int数值进行缓存。Python缓存到256
“`

  • 综上:在方法中修改不可变类型的参数时,方法外并不会体现**

Python高级主题

CPython(Python 解释器)

一说到编译器和解释器,Java虚拟机总是有很多说不完的话题如内存模型、垃圾回收、类加载和优化等,但是Python的解释器CPython甚至在许多Python的书中没有一个小节去介绍。

多线程和锁

创建多线程

import threading

def thread_my():
    thread = threading.current_thread()
    print 'thread name --'
    print thread.getName()

t = threading.Thread(target=thread_my)
t.start()

thread_my()
t.join()

锁的使用

经典的 n += 1问题看看Python用锁怎么处理

import threading

n = 0
lock = threading.Lock()

def foo():
    global n
    with lock:
        n += 1

threads = []
for i in range(100):
    t = threading.Thread(target=foo)
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

print(n)

尴尬的锁

线程和锁在原生Python中概念非常弱化甚至有些不友好。基本上源于CPython的全局解释器锁(GIL),它的设计目的是保证同一时刻只能有一个线程在运行。在IO比较密集的任务的单核机器略显吃力。

static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */

上面是Cpython的 ceval.c的一段源码,解释器中所有代码执行的时候都需要保持这个锁。

那么这个锁什么时候释放那?

  • 一个线程无论何时开始睡眠或等待网络 I/O其他线程总有机会获取 GIL 执行 Python 代码,这是协同式多任务处理
  • 如果一个线程不间断地在 Python 2 中运行 1000 字节码指令,或者不间断地在 Python 3 运行15 毫秒,那么它便会放弃 GIL,这是抢占式多任务处理

可以把Python想象成2000年单核cpu的年代的机器,多个任务抢占一个cpu,而Python是多个线程抢占一个GIL

为什么说原生Python在多核任务中略显吃力

def dead_loop():
    while True:
        pass

dead_loop()

上面这段代码如果跑在双核cpu的机器上,会发现只是占用50%的cpu。那按照Java的思路如何跑满两个核,ok再创建一个线程继续跑

import threading

def dead_loop():
    while True:
        pass

t = threading.Thread(target=dead_loop)
t.start()

dead_loop()

t.join()

但是问题出现了,效果还是只有50%的占用率,并没有跑满两个核,这里面的原因就是因为GIL。为什么Python作者这么设计,Python中没有去掉GIL。去掉全局锁必然会带来细粒度的锁或者Lock-free模式,在1999年做过一个分支去掉了GIL,但是在测试过程中发现单线程的效率降低了两倍,并且随着cpu的增加效率的提升并不是线性的,而是非常缓慢,可以看下开发者的Greg’s写的信 Gregs Free threading

Python的并行

因为存在着GIL,导致Python的线程不能实现真正意义上的并行,但是也并不是没有办法处理

  • 采用多进程处理,这样失去了线程间的共享变量和通信的便利了
  • 通过ctypes引入c代码来实现真正意义上的并行

Web编程

Web系统架构

Alt 系统架构

  • 一般网络架构从上层到下层包括:DNS服务器->LVS服务器->应用容器->应用系统
  • 在开发过程中只需要关注应用容器和应用系统就好,在Java中应用容器有Resin、Tomcat、Jetty等。应用系统框架有EJB、Spring、Struts等
  • Python中应用系统框架有Django、Flask、Tornado。Python中没有容器的概念,但是大同小异Python把容器拆成公共规范(WSGI)和中间件,而公共规范和中间件加一起所做的事情又非常类似Java中的容器(servlet容器和连接器)。servlet容器约定了调用service()方法,应用框架或者程序需要实现servie(),连接器负责包装request和response给servlet容器。同样的WSGI里面预定了相应的应用框架和程序需要时间的方法,而中间件负责将request和response进行封装
  • WSGI 的全称是Web Server Gateway Interface,他是一个规范。它所做的事情和servlet类似,让应用程序可以很方便的在各种应用容器上进行迁移,不必因为用了某个特定容器而使用指定的应用框架,也不必因为用了某个特定框架而实用指定容器。想要深入了解可以看下PEP333。还有中文介绍理解WSGI

Python应用框架

Instagram是Python的重度依赖用户,Instagram 的总注册用户达到 30 亿,月活用户超过 7 亿 (作为对比,微信最新披露的月活跃用户为 9.38 亿)。而令人吃惊的是,这么高的访问量背后,竟完全是由以速度慢著称的 Python + Django 支撑

Flask & Django

业界比较成熟的两个框架,有一篇关于两者对比的文章Flask VS Django,主要阐述了Flask小而灵活,只包含了必要的模块。而Django大而全,比较臃肿,会默认引入许多模块

Flask实现简单服务
安装pip(官网标准http://flask.pocoo.org/docs/0.12/installation/#installation)
windows步骤:
(1)下载https://bootstrap.pypa.io/get-pip.py
(2)执行python get-pip.py install
(3)将Python27\Scripts加入到环境变量
(4)pip install Flask
(5)创建hello.py


from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'


$ set FLASK_APP=hello.py
$ flask run

 访问http://127.0.0.1:5000/

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值