zoukankan      html  css  js  c++  java
  • 聊聊我对python的感受

    工作中主要是在写python2,把python作为用户逻辑的载体的,一般是C++写好底层,导出成python模块使用,或者是可执行程序带起来一个python虚拟机,把函数注入进去,然后加载python代码执行。我接触的这部分python,没有太多的框架,几乎不使用基本数据结构之外的标准库,因为很多东西都是C++封装好给python的,性能比纯python好很多。因此下面的文字也主要围绕着我使用的这个python的子集展开,如果有所偏差,那也是无法避免的。

    python的一些优点

    hook一切的能力

    python的装饰器提供了一种在定义处直接修改被定义的对象的能力,有点类似清洁宏。宏这种东西,目的就是对语言的语法树做变换,生成被调整过的语法树结构,来达到抽象某些东西的意义。然而大部分加宏,尤其是清洁宏的语言,都不可避免的要考虑一个问题,就是如何表示语法树和语法树的变换。Lisp系因为本身代码就是数据,所以语法树,代码,变换都是S-expr;rust则是发明了另一套语法来做这一件事情;还在proposal阶段的C++ reflection,不仅要发明语法,还要发明对应的库和namespace,甚至还要和constexpr之类的东西耦合,这就很丑,而且又很大地增加了语言的复杂度。不喷C++了,python的装饰器很巧妙的复用了python语法,通过放弃一些变换的自由度的方式(装饰器只能以函数/类为单位进行变换)实现了较为舒服的宏。

    另一个要说的就是metaclass,metaclass用来hook类型的创建,可以用来做一些在类型创建时对类型进行调整的工作,比如增减类变量,修改基类,注册一些东西,变换一下函数等等。

    最后就是属性索引器__get__和__set__,我曾经在看到他们之后突然意识到,这就是C#的DependencyProperty需要的东西,不通过用户编写代码,来达到hook一个属性的读取和写入的能力。写过WPF的同学都知道,WPF里面有一套很复杂的DependencyProperty/Object系统,其实说白了就是需要hook属性更改,用来做数据绑定之类的东西,写起来很麻烦,VS也专门提供了插入dependency property定义的boilerplate的功能。python这个属性索引器设计就很好的解决了这个问题,至少让代码写起来没有那么多废话了。

    有人可能觉得我用C++和C#跟python对比不合适,的确,这些语言的主战场是大型系统,高性能,硬件抽象,的确不适合用来实现过于灵活的东西。

    不吝于用开洞的方法来解决问题

    python有很多魔术方法,而且随着语言的进化,还在加入更多的魔术方法。对象构造走魔术方法,运算符重载走魔术方法,上面说的hook属性索引器也是魔术方法,甚至检查一个类是不是另一个的基类,也可以走魔术方法。当语言层面原生为你提供很多hook的时候,尤其是需要灵活性的动态语言,他的灵活性就真的有了。反观C++一直在吹嘘我们可以用抽象来实现一切东西,然后写出来的东西都是一坨一坨的模板,然后initializer_list,structured binding,attribute还是忍不住开了洞。C#这样语法还算很优雅的语言,也需要一堆boilerplate来做dependency property。当然他们都是静态语言,主战场是性能,本来就不应该和动态语言相比较。

    另一个要说的就是__getitem__和__setitem__,python的obj[key]和obj[key]=value走了两个不同的方法,这样就很棒地绕开了key不存在时到底是要添加,还是丢异常的问题。因为分开了读取和写入,obj[key],不存在丢异常,obj[key]=value,不存在就添加,和C#/C++的Dictionary/map设计相比好了不少,这俩一个不存在都丢异常,一个不存在都添加。

    与C++杂乱的开洞相比,python的洞基本都开在魔术方法上,位置相对比较统一。

    python的垃圾之处

    智障缩进/换行语法

    强制缩进,换行,python是唯一一个lambda会降低代码可读性的语言。就没听说过其他哪个语言的lambda会让代码可读性变差的

    强行换行用,尤其是当if条件稍微长一点的时候,你不想用,把if拆开,就得缩进好几个tab,你用换行,看着就跟C++写了一坨宏似的

    基本控制流太少

    虽然传统的for、do-while都可以变换成while来做,但是while True: if xxx break很丑哎,加个do-while又不会怀孕

    虽然switch可以用dict+lambda做,但lambda都那么丑了,我又不想白白产生一个构造dict的overhead,只能写一坨if else

    真的慢,没有jit,没有内联优化,没有逃逸分析,对象全都开在堆上,引用计数+mark sweep也慢,处理个数组能比C++慢两个数量级,小函数调用特别伤。

  • 相关阅读:
    jackson 枚举 enum json 解析类型 返回数字 或者自定义文字 How To Serialize Enums as JSON Objects with Jackson
    Antd Pro V5 中ProTable 自定义查询参数和返回值
    ES6/Antd 代码阅读记录
    es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?
    Antd Hooks
    使用.Net Core开发WPF App系列教程(其它 、保存控件内容为图片)
    使用.Net Core开发WPF App系列教程( 三、与.Net Framework的区别)
    使用.Net Core开发WPF App系列教程( 四、WPF中的XAML)
    使用.Net Core开发WPF App系列教程( 二、在Visual Studio 2019中创建.Net Core WPF工程)
    使用.Net Core开发WPF App系列教程( 一、.Net Core和WPF介绍)
  • 原文地址:https://www.cnblogs.com/pointer-smq/p/10091063.html
Copyright © 2011-2022 走看看