V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
chinesehuazhou
V2EX  ›  Python

聊聊技术写作的个人体会(内有公众号宣传,不喜勿进)

  •  
  •   chinesehuazhou · 2019-01-11 22:08:49 +08:00 · 1491 次点击
    这是一个创建于 2161 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有群友问过,是什么原因使我开始写技术公众号,又是什么动力让我坚持写的。

    在我看来,写作是一件不能敷衍的事,通过写作来学习,反而要比单纯地学习的效果要好。为了写成一篇“拿得出手”的文章,我要反复查找资料,阅读与思考,拆解与整合,最终写成的时候,也是知识的拼图成型的时候。

    所以,对我来说,**写作是一种咀嚼信息而后提炼知识,最终拓展成技能与认知的过程。**虽然这个过程很缓慢,但曾经的急进方式并没有速成的效果啊,不妨就这样一文章一脚印地试试看咯。

    除此之外,还有一个很重要的原因。文章是一种公共对话的媒介,它是一个展示的窗口,也是一个接收反馈的通道。通过写作,我有了跟其它学习者对话的机会。

    看书学习可能只是个人的事情,但是,在写作平台上发布文章,这就超越了个人行为——你得随时准备着被批评、或者被请教、或者被误解、甚至是被无视(这是最常见的结果)。

    我享受写作文章,来跟其他处在相同处境的同学们交流,来向更优秀的大牛们学习取经。

    这就是我目前写技术文章的一些个人体会吧。

    对于上面提到的第二个原因,我最近颇有感触,想要多聊一些。为了更有针对性,本文姑且限定一个话题吧,那就是“写作技术文章,如何看待他人的批评 /意见”。

    1、主观性的意见

    有些声音其实只是主观看法,我认为可以和而不同。

    主观世界往往没有确切的对错之分,毕竟——思想无罪

    面对主观性的意见,我认为要做到有理有据,坚持一点个性,最后会得到别人的尊重。

    比如,在翻译 Python 社区的七种治理模式的时候,有一个提案是“ Python Governance Model Lead by Trio of Pythonistas ”,我将它翻译成“三巨头治理模式”。有同学就指出,“ Trio ”应该翻译成“三人组”或者“三重奏”,翻译成“三巨头”是什么意思?

    这种留言,我认为是主观性的意见,应求同存异。

    我之所以这么翻译,一方面考虑,它要替代的是“终身仁慈独裁者”,三巨头对独裁者,意味深长;另一方面,我脑子里总想着一个皇帝死了,然后政权被三个摄政大臣把持,这种政治画面挥之不去,虽然是不着边际,但挺有趣味,所以我不肯放弃这“三巨头”的译法。

    主观性的意见带入了提出者的个人知识背景、思想结构、以及话语习惯等等,我觉得要先尝试交流,相互交换,能融洽兼容则最好啦,不能的话,及时终止。

    2、客观性的意见

    客观性的意见有如下几种:笔误(错别字和其它疏忽)、代码规范、知识性错误......

    对于笔误性的错误,这没啥好说的,我自己发现过几处,也被读者指出过几处。有则改之就好。

    对于代码规范,有时候为了举例方便,确实没有按照规范来。尽量避免,求一个兼顾。

    知识性错误是要热烈欢迎的——不是说欢迎错误,而是说欢迎别人来指出我所未知的错误。

    出现知识性的错误,就意味着没有全面掌握知识,一旦出现,就必然意味着有提升的空间。本来以为知道了什么,如果被指出了错误,那改正后,才是真的知道了什么。

    知道自己不知道并且改正之,并不可耻,不知道自己不知道,这才可怜。

    在写《Python 是否支持复制字符串呢?》的时候,我根据已得的知识,以及查阅到的资料,早早就得出了一个很满意的结论。最后成文前,临时地加了一个未作验证的示例,没想到这会是一个致命的反例,推翻了前面辛辛苦苦建立起来的一切。

    这是一个客观性的错误,一被指出的时候,很快就能验证。因为这个错误,我重新梳理了相关的知识点,组成新的知识面,写成了一篇《join()方法的神奇用处与 Intern 机制的软肋》。

    还有一个例子,前不久的《Python 进阶:自定义对象实现切片功能》,我在准备素材的时候,竟采用了一个不严谨的例子,而且自作聪明地批判了别人的实际无误的例子。最后,有读者留言了很长的不同观点,我才意识到自己的错误!

    得益于读者的留言,我修正了自己的错误,而且在修正过程中,也加强了对于其它知识的理解,真是塞翁失马焉知非福啊。

    3、内置函数与内置类

    这里还有一个客观性错误,藏得特别深,可能真的有 90% 的 Python 使用者不知道。

    特别感谢 @xpresslink 同学指出。下面,我给大家分享一下。

    在文章《为什么 range 不是迭代器? range 到底是什么类型?》里,我的注意点其实就在标题的两个问句里,大部分的留言互动也是基于此。但最后,很意外地,一名读者指出了一个客观性错误,让我有了额外的收获。

    这位同学指出我有些基本的概念是错误的:

    “ range() 函数”这个说法是非常明显有错误的,range 不是内置函数( builtin method )而是个类对象,在 python 里面不要见到用括号调用的东西就认为是函数,类似的还是有很多,如 list, set, tuple, dict 等,这些都是类, 特别是 enumerate,这个学 python 的人十有八九认为是函数而不知道是类,加了括号是实例化而不是函数调用。

    python 中类的实例化和函数调用非常容易对新手有大的迷惑性,相对来说在 java 中有明确的 new 关键字加在构造方法前面概念更清楚一些。

    根据这个评论,我就去查看文档。

    上图中 range() 虽然被归类到 Built-in Functions 里面,但是官方描述的是“ functions and types ”,即是说,在内置函数的大类下面,包含了内置函数与内置类。

    那 range() 属于哪一种呢?看看它的解释:

    Rather than being a function, range is actually an immutable sequence type......

    range 实际是一种不可变的序列类型,而非一个(内置)函数......

    按照这里的说法,官方已经区分了 range() 不是函数,正像那位留言的同学所说。

    我第一反应当然是不能接受。我怎么会认为它是内置函数的呢,难道不是根据学习资料得来的么?难道我学习的资料是错的?为何从来没看到有人对此做过辨析呢?

    根据群友的提示,我去查看 Python2 的文档,然后就发现了很有意思的地方:

    首先一点,Built-in Functions 的描述跟 Python3 有点不同,它写的是 “ functions ”,并不包含“ types ”;还有一点,在 range() 和 xrange() 的具体内容中,官方都是称呼它们为 function。

    由此看来,Python2 的官方文档就把 range() 当成内置函数,这个认识错误是有根源的!等到 Python3 的时候,官方把错误改正过来了,然而改得并不彻底。才有了前面同时存在“ functions and types ”的描述。

    官方已经把 range() 与 xrange() 规范为一个,或许在今后版本,还会专门分出一类 Built-in Types 来存放像 range() 和 enumerate() 这些内置类吧。

    在那之前,我只能先行给大家提个醒了:别再误以为 range() 是内置函数了。

    那么,怎么辨别哪些是内置函数呢?

    我想到了两个方法:

    ( 1 )看是否存在对应的魔术方法。例如,len() 是一个内置函数,因为它实际调用的是魔术方法__len__() ;还有最近一直在提的 iter(),它调用的是__iter__() ,所以也是内置函数;而因为不存在 __range__() 魔术方法,所以 range() 不是内置函数。

    ( 2 )使用 type() 进行判断,结果为 builtin_function_or_method 的才是内置函数。

    >>> type(len)
    builtin_function_or_method
    >>> type(sorted)
    builtin_function_or_method
    >>> type(open)
    builtin_function_or_method
    
    >>> type(range)
    type
    >>> type(enumerate)
    type
    >>> type(str)
    type
    

    像 open 和 sorted 并没有对应的魔术方法,但判断出来都是内置函数;而 str 虽有对应魔术方法,但判断是 type,这意味着,以上两种方法得要结合起来看。

    我不确定有多少人事先知道怎么区分内置函数与内置类,但我确实没看到过对这个问题进行辨析的文章,所以,这次是真正涨知识了,也希望这篇文章,能够消除一些读者的错误观念吧。

    4、小结

    我最近写的一些文章都不是心血来潮,不管是字符串系列、切片系列还是迭代器系列,本意都是想在一个主题上进行深入的多面性的思考与记录。

    如果没有一些热心读者的指正,我恐怕是很难知道自己错在了哪里,如果不是有这么多的认同以及意见,我恐怕也缺乏动力坚持写下去。

    最后鸣谢几位提意见的小能手同学(时间顺序,可能有漏):@疯琴、 @德玛西亚之翼奎因、 @发条橙、 @gaieepo、 @郭芮、 @aijam、 @xpresslink、 @进击的团子、 @不换......

    相关链接(单有错,双修正):

    1、Python 是否支持复制字符串呢?

    2、join()方法的神奇用处与 Intern 机制的软肋

    3、Python 进阶:自定义对象实现切片功能

    4、Python 进阶:全面解读高级特性之切片!

    5、为什么 range 不是迭代器? range 到底是什么类型?

    -----------------

    本文原创并首发于微信公众号 [ Python 猫] ,后台回复“爱学习”,免费获得 20+本精选电子书。

    2 条回复    2019-01-12 18:33:32 +08:00
    aijam
        1
    aijam  
       2019-01-12 17:27:58 +08:00
    目测 lz 理解有点偏啊。
    1. 生拉硬套把 magic method 和是否是 builtin_function_or_method 联系起来,问题是他们虽然使用上有一点关系但没必然关联啊。
    2. 逻辑不通,明明说了“使用 type() 进行判断,结果为 builtin_function_or_method 的才是内置函数”,后面得出的结论是要“以上两种方法得要结合起来看”。没看出 type()有什么地方不够用的啊。
    3. 如果 lz 纠结是 range 是不是 builtin_function_or_method,那这是一个 trivial 的问题,调用 type 即可。如果 lz 纠结的是 range 到底是 function 还是 type,python 里面 function 本身是一个非常非常宽泛概念,比如 lambda/callable/generator function/classmethod/instancemethod/staticmethod 你怎么界定他们是不是 function。用 Python 的人更多的是问是否是 callable 这个比较实际的问题,比如有 callable(...)和 typing.Callable 却没有 isfunction(...)和 typing.Function。
    4. str/list/range 即是 type 也是 constructor。constructor 是特殊的 function,用来构造 type 的 instance,那说 range 是 function 也不是不可。比如 str(123)里它就是 constructor,isinstance('123', str)里它就是 type。如果你了解一点 Haskell 里 type constructor 和 data constructor 的差别,这点道理就比较好理解。
    不客气的说:lz 发现了 range type 的存在,然后通过自己的联想给了一个蹩脚的解释。
    chinesehuazhou
        2
    chinesehuazhou  
    OP
       2019-01-12 18:33:32 +08:00
    @aijam 谢谢这么认真的回复。关于魔术方法的那点,是我欠考虑了,只留下 type 就够了。我原本只考虑 builtin_function_or_method,多谢你提出关于 constructor 的内容,受教了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5516 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 02:41 · PVG 10:41 · LAX 18:41 · JFK 21:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.