GVKun编程网logo

什么比“不”更“ pythonic”(什么比不什么)

12

针对什么比“不”更“pythonic”和什么比不什么这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展ios–在Swift中,为什么“让_=this”比“this!=nil”更快?、Ironi

针对什么比“不”更“ pythonic”什么比不什么这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展ios – 在Swift中,为什么“让_ = this”比“this!= nil”更快?、Ironic Python Agent Python 代理、java为什么比python快、Lua 的速度为什么比 Python 快?等相关知识,希望可以帮助到你。

本文目录一览:

什么比“不”更“ pythonic”(什么比不什么)

什么比“不”更“ pythonic”(什么比不什么)

我已经看到了两种方式,但是哪种方式更适合Python?

a = [1, 2, 3]# version 1if not 4 in a:    print ''is the not more pythonic?''# version 2if 4 not in a:    print ''this haz more engrish''

哪种方法被认为是更好的Python?

答案1

小编典典

第二个选项是Pythonic,原因有两个:

  • 它是 一个 运算符,转换为一个字节码操作数。另一行是真的not (4 in a); 两个操作员。

碰巧的是,Python会 优化
后一种情况并转换not(x in y)x not in y任何情况,但这是CPython编译器的实现细节。

  • 这接近于您在英语中使用相同逻辑的方式。

ios – 在Swift中,为什么“让_ = this”比“this!= nil”更快?

ios – 在Swift中,为什么“让_ = this”比“this!= nil”更快?

所以我的问题是为什么让_ =这比这快!= nil?

例:

这是:

let this : Bool? = true //

let start = dispatchTime.Now()
for _ in 0...100000000  {
    guard this != nil else { continue }
}
let end = dispatchTime.Now()

let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime)
print("Time \(timeInterval)") 

         // Time 5426559135.0
         // Time 5428084767.0
         // Time 5327325459.0

慢于:

let this : Bool? = true //

let start = dispatchTime.Now()
for _ in 0...100000000  {
    guard let _ = this else { continue }
}
let end = dispatchTime.Now()

let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime)
print("Time \(timeInterval)")

          // Time 257045414.0
          // Time 261933863.0
          // Time 263465919.0

解决方法

在 Jonathan的 response之后,我检查了实际的反汇编指令.
结果如下:
对于代码:

let this : Bool? = nil
this != nil

我们得到:

0x100001290 <+0>:  pushq  %rbp
    0x100001291 <+1>:  movq   %rsp,%rbp
    0x100001294 <+4>:  subq   $0x30,%rsp
    0x100001298 <+8>:  leaq   0x2c7259(%rip),%rdx      ; type Metadata for Swift.Bool
    0x10000129f <+15>: leaq   0x2b66ca(%rip),%rcx      ; protocol witness table for Swift.Bool : Swift.Equatable in Swift
    0x1000012a6 <+22>: leaq   -0x18(%rbp),%rax
    0x1000012aa <+26>: leaq   -0x8(%rbp),%r8
    0x1000012ae <+30>: movb   $0x2,0x2f940b(%rip)
    0x1000012b5 <+37>: movb   0x2f9404(%rip),%r9b      ; test2.this : Swift.Optional<Swift.Bool>
    0x1000012bc <+44>: movb   %r9b,-0x8(%rbp)
    0x1000012c0 <+48>: movb   $0x2,-0x10(%rbp)
    0x1000012c4 <+52>: movb   -0x10(%rbp),%r9b
    0x1000012c8 <+56>: movb   %r9b,-0x18(%rbp)
    0x1000012cc <+60>: movl   %edi,-0x1c(%rbp)
    0x1000012cf <+63>: movq   %r8,%rdi
    0x1000012d2 <+66>: movq   %rsi,-0x28(%rbp)
    0x1000012d6 <+70>: movq   %rax,%rsi
    0x1000012d9 <+73>: callq  0x10004df10               ; Swift.!= infix <A where A: Swift.Equatable> (Swift.Optional<A>,Swift.Optional<A>) -> Swift.Bool
    0x1000012de <+78>: xorl   %r10d,%r10d
    0x1000012e1 <+81>: movb   %al,-0x29(%rbp)
    0x1000012e4 <+84>: movl   %r10d,%eax
    0x1000012e7 <+87>: addq   $0x30,%rsp
    0x1000012eb <+91>: popq   %rbp
    0x1000012ec <+92>: retq

并为:

let this : Bool? = nil
let _ = this

有:

0x1000012d0 <+0>:  pushq  %rbp
    0x1000012d1 <+1>:  movq   %rsp,%rbp
    0x1000012d4 <+4>:  xorl   %eax,%eax
    0x1000012d6 <+6>:  movb   $0x2,0x2f93e3(%rip)
    0x1000012dd <+13>: movl   %edi,-0x4(%rbp)
    0x1000012e0 <+16>: movq   %rsi,-0x10(%rbp)
    0x1000012e4 <+20>: popq   %rbp
    0x1000012e5 <+21>: retq

另外,谢谢Code Different指向优化级别.

将值从[-Onone]更改为[-O -whole-module-optimization]将导致生成的asm按以下方式更改:

let this : Bool? = nil
let _ = this

具有

0x100001490 <+0>:  pushq  %rbp
    0x100001491 <+1>:  movq   %rsp,%rbp
    0x100001494 <+4>:  movb   $0x2,0x3d9595(%rip)      ; gCRAnnotations + 63
    0x10000149b <+11>: xorl   %eax,%eax
    0x10000149d <+13>: popq   %rbp
    0x10000149e <+14>: retq

let this : Bool? = nil
this != nil

0x100001490 <+0>:  pushq  %rbp
    0x100001491 <+1>:  movq   %rsp,%eax
    0x10000149d <+13>: popq   %rbp
    0x10000149e <+14>: retq

所以结果指令实际上是相同的,执行它们的时间应该非常接近.

Ironic Python Agent Python 代理

Ironic Python Agent Python 代理

Ironic Python Agent 介绍

Ironic Python Agent 是用于撤销和配置裸机服务的 Python 代理。Ironic Python Agent 的代理由 Ironic
提供的节点驱动。Ironic Python Agent 从未接通的节点上开始运行,然后让 API 调用 Ironic Python Agent 来提供机器。

Ironic Python Agent 官网

https://github.com/openstack/ironic-python-agent

java为什么比python快

java为什么比python快

Python慢,这几种是常见的原因:“因为它是GIL(全局解释器锁)”,“因为它是解释语言不是编译语言”,“因为它是动态类型语言”。

推荐课程:Java教程。

究竟哪个原因对性能的影响最大?

“因为它是GIL”

现代计算机的 cpu 有多个核心,有时甚至有多个处理器。为了利用所有计算能力,操作系统定义了一个底层结构,叫做线程,而一个进程(例如 Chrome浏览器)能够生成多个线程,通过线程来执行系统指令。这样如果一个进程是要使用很多 cpu,那么计算负载就会由多个核心分担,最终使得绝大多数应用能更快地完成任务。

在撰写本文时,我的 Chrome 浏览器开了 44 个线程。另外,基于 POSIX 的操作系统(如 Mac OS 和 Linux)的线程结构和 API 与 Windows 操作系统是不一样的。操作系统还负责线程的调度。

如果你没写过多线程程序,那么你应该了解一下锁的概念。与单线程进程不同,在多线程编程中,你要确保改变内存中的变量时,多个线程不会试图同时修改或访问同一个内存地址。

cpython 在创建变量时会分配内存,然后用一个计数器计算对该变量的引用的次数。这个概念叫做“引用计数”。如果引用的数目为 0,那就可以将这个变量从系统中释放掉。这样,创建“临时”变量(如在 for 循环的上下文环境中)不会耗光应用程序的内存。

随之而来的问题就是,如果变量在多个线程中共享,cpython 需要对引用计数器加锁。有一个“全局解释器锁”会谨慎地控制线程的执行。不管有多少个线程,解释器一次只能执行一个操作。

这对 Python 应用的性能有什么影响?

如果应用程序是单线程、单解释器的,那么这不会对速度有任何影响。去掉 GIL 也不会影响代码的性能。

但如果想用一个解释器(一个 Python 进程)通过线程实现并发,而且线程是IO 密集型的(即有很多网络输入输出或磁盘输入输出),那么就会出现下面这种 GIL 竞争:

640?wx_fmt=png

如果 Web 应用(如 Django)使用了 Wsgi,那么发往 Web 应用的每个请求都会由独立的 Python 解释器执行,因此每个请求都只会有一个锁。由于 Python 解释器启动很慢,一些 Wsgi 实现就支持“守护模式”,保持 Python 进程长期运行。

“因为它是解释语言”

这条理由我也听过很多,我发现它过于简化了 cpython 的实际工作原理。当你在终端上写 python myscript.py 时,cpython 会启动一长串操作,包括读取、词法分析、语法分析、编译、解释以及执行。个过程的重点就是它会在编译阶段生成.pyc文件,字节码会写到__pycache__/下的文件中(如果是Python 3),或者写到与源代码同一个目录中(Python 2)。不仅你编写的脚本是这样,所有你导入的代码都是这样,包括第三方模块。

因此绝大多数情况下(除非你写的代码只会运行一次),Python是在解释字节码并在本地执行。与Java和C#.NET比较一下:

Java将源代码编译成“中间语言”,然后Java虚拟机读取字节码并即时编译成机器码。.NET CIL也是一样的,.NET的公共语言运行时(CLR)使用即时编译将字节码编译成机器码。

那么,既然它们都使用虚拟机,以及某种字节码,为什么Python在性能测试中比Java和C#慢那么多?第一个原因是,.NET和Java是即时编译的(JIT)。

即时编译,即JIT(Just-in-time),需要一种中间语言,将代码分割成小块(或者称帧)。而提前编译(Ahead of Time,简称AOT)是编译器把源代码翻译成cpu能理解的代码之后再执行。

JIT本身并不能让执行更快,因为它执行的是同样的字节码序列。但是,JIT可以在运行时做出优化。好的GIT优化器能找到应用程序中执行最多的部分,称为“热点”。然后对那些字节码进行优化,将它们替换成效率更高的代码。

这就是说,如果你的应用程序会反复做某件事情,那么速度就会快很多。此外,别忘了Java和C#都是强类型语言,所以优化器可以对代码做更多的假设。

“因为它是动态类型语言”

“静态类型”语言要求必须在变量定义时指定其类型,例如C、C++、Java、C#和Go等。

而动态类型语言中尽管也有类型的概念,但变量的类型是动态的。

a = 1
a = foo

在这个例子中,Python用相同的名字和str类型定义了第二个变量,同时释放了第一个a的实例占用的内存。

静态类型语言的设计目的并不是折磨人,这样设计是因为cpu就是这样工作的。如果任何操作最终都要转化成简单的二进制操作,那就需要将对象和类型都转换成低级数据结构。

Python帮你做了这一切,只不过你从来没有关心过,也不需要关心。

不需要定义类型并不是Python慢的原因。Python的设计可以让你把一切都做成动态的。你可以在运行时替换对象的方法,可以在运行时给底层系统调用打补丁。几乎一切都有可能。

而这种设计使得Python的优化变得很困难。

那么,Python的动态类型是否让Python更慢?

比较并转换类型的代价很大。每次读取、写入或引用变脸时都会检查类型

动态类型的语言很难优化。许多替代Python的语言很快的原因就是它们牺牲了便利性来交换性能。

例如Cython(http://cython.org/),它通过结合C的静态类型和Python的方式,使得代码中的类型已知,从而优化代码,能够获得84倍的性能提升

总结

Python慢的主要原因是因为它的动态和多样性。它能用于解决各种问题,但多数问题都有优化得更好和更快的解决方案。

但Python应用也有许多优化措施,如使用异步、理解性能测试工具,以及使用多解释器等。

对于启动时间不重要,而代码可能享受到JIT的好处的应用,可以考虑使用PyPy。

对于代码中性能很重要的部分,如果变量大多是静态类型,可以考虑使用Cython。

Lua 的速度为什么比 Python 快?

Lua 的速度为什么比 Python 快?

Lua 和 Python 同为虚拟机解释型脚本语言,为什么 Lua 的执行速度比 Python 高?

回复内容:

前面几位已经说的很好,我来做一下补充。

@冯东 和 @庞巍伟 都提到了Lua使用的是register-based的虚拟机设计,我看到下面有人评论说既然这种VM的设计性能高,那么为什么Python和java还是使用的stack-based的设计。

我的理解是实现难度吧,register-based的设计中,一个操作需要关注到指令的操作数到底存放在哪里,而stack-based的不需要,它分开了几条指令,首先加载数据到栈顶,然后再进行操作,操作时默认的认为数据就存在栈顶了。(如果不清楚这个过程,可以拖上去看看 @庞巍伟 的回答,就不在这里列出来了)

简单的说,register-based的指令格式设计把stack-based的指令中分几条指令要完成的事情用一条指令搞定了,快当然是快了,难度也加大了。

另外还有一点上面的回答中似乎没有提到,Lua使用的是一遍遍历就生产指令的方式,学过编译原理的,大概都能知道一般分两遍遍历,第一遍生成AST,再一遍遍历AST生成指令,而在Lua中是直接跳过了AST指令这一步的。

还是那句话,快是快了,代码的实现难度也大了些。最早的Lua解释器,也是使用lex、yacc这样的工具来自动生成代码的,后来为了提升性能,作者改成了自己手写的递归下降的分析器。这部分代码是我认为Lua代码中最难理解的一个部分了--因为它要一遍分析干太多的事情了。

我在阅读Lua代码的过程中,能充分感受到作者为了Lua在性能上的提升花费的心血,致敬。 有一些 PUC-Rio Lua(也就是没 JIT 的)和 Python 的 benchmark 对比。结论是 Python 比 C 大约慢 70 倍,Lua 大约慢 30-40 倍。

Lua 是 register-based VM。所谓的寄存器,其实并不神秘,就是 runtime stack 的 topmost frame [1] 是可以被 VM 指令随机访问的。至于为什么 CPU 里的某种硬件也叫寄存器,原因在这里有解释:《什么是寄存器》。

Stack frame 可以被随机访问之后,在同一个 VM 指令里就可以用 native code 一次做很多事情。

可以看云风的这篇 blog:《云风的 BLOG: 虚拟机之比较,lua 5 的实现
  1. Stack frame 就是 stack 中属于同一个 function invocation 的所有 stack entries。
首先lua的虚拟机非常简单,指令设计也很精简.

最关键的是, lua 是基于寄存器的虚拟机实现,而python还有很多其他脚本语言是基于堆栈的,基于寄存器的虚拟机字节码更简单,更高效,因为register based vm的字节码,一般同时包含了指令/操作数/操作目标等.

对比简单的加法操作:

stack based 生成的字节码大概是这样(仅仅是模拟,不代表实际)

PUSH 1
PUSH 2
ADD // ADD 的操作结果存放eax
PUSH eax // 将结果push入堆栈,以便后面的代码不会覆盖eax

而register based 生成的字节码大概是这样:
ADD 1,2,R1
就一行,R1存放1+2的结果

就这么简答的操作就已经相差4条指令,所以基于寄存器的虚拟机字节码运行更有效率. python的一些设计特性,例如完全面向对象,同时也是它在性能表现上的负担。
举个很简单的例子:
<span>def</span> <span>test</span><span>():</span>
    <span>a</span> <span>=</span> <span>1</span>
    <span>b</span> <span>=</span> <span>2</span>
    <span>return</span> <span>a</span> <span>+</span> <span>b</span>
登录后复制
Lua的语言特性设计的很紧凑,在各方面进行优化的困难路径都比JS和Python少(得多), Python基于纯对象的, 任意东西都是对象. 所以数值运算时, 还要进行转换
lua 最新的5.3 已经支持整数类型, 加上基于寄存器的VM和优秀的编译器, 想慢都难 抛个砖,引个玉。

1. 基于栈和基于寄存器的不同是主要的性能差异原因。这点大家也都解析的非常清楚了,也很好想象。基于栈的求值过程必须使用栈顶的值,想想也知道是反人类的(哦不,反机器的-_-!)。因此会出现很多的push(load)和pop(store)指令,而基于寄存器的指令就一条完事了。但这都是在解释执行的情况下,如果编译到本地指令之后,理论上来说,基于寄存器还是基于栈的实现并没有太多影响,因为都转换成了硬件寄存器,两者的转换过程的开销也没有太多差别。
2. 为什么采用基于栈的虚拟机,除了实现简单(后序遍历AST就有了)之外,占用空间小也是一个基于栈的虚拟机的特点,便于网络传输和嵌入式设备。Java在设计之初就是考虑到网络方面的应用,比如Applet技术,以及嵌入式设备的运用。
3. 个人还有一个想法,不知道是否靠谱@RednaxelaFX。基于栈的虚拟机的指令更加完整地保留了源代码的求值过程,几乎是AST直接『压平』的结果,甚至很容易逆回源代码。这就意味着基于栈的指令在后续操作中可以很容易转换成需要的形式,以便于在不同的形式上做优化。栈代码转换成寄存器代码没有什么效率影响,而寄存器代码转换成栈代码就会出现比遍历AST生成还要多的push(load)和pop(store)指令。栈代码的生成适合直接从AST后续遍历得到,因为求值的过程都是围绕着栈顶。简而言之,栈代码是一个可塑性比较强的代码,先存着,后面想怎么处理都保留了可能性。
4. 语法分析到代码生成过程减少pass数,个人觉得并没有太大的意义。严格来讲这个过程的效率应该不能算是performance的效率,最多只是加快了从源码的启动时间。Performance应该从解释执行开始比较。有的时候单趟编译造成了复杂性反而得不偿失,AST这样的数据结构就适合在上面干该干的事。
5. 实际中虚拟机的效率还和很多其他啊因素有关。比如很重要的方面就是垃圾回收。
6. 至于上升到指令集设计高度的话,不太了解,请R大来。 @RednaxelaFX。他应该会贴个这个传送门虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 Lua的指令集非常非常非常简单,我对着指令说明看了半个小时就能看懂lua的汇编代码了,再花十来分钟就能手动修改lua二进制代码了。而我甚至没完整看过lua的源码。 占坑 以我的观点,最大的关键是在 lua 在语言层面相比 python 简单了很多,所以他们的实现相应的就有了速度的差别。

今天关于什么比“不”更“ pythonic”什么比不什么的讲解已经结束,谢谢您的阅读,如果想了解更多关于ios – 在Swift中,为什么“让_ = this”比“this!= nil”更快?、Ironic Python Agent Python 代理、java为什么比python快、Lua 的速度为什么比 Python 快?的相关知识,请在本站搜索。

本文标签: