数字转中文

发布在 编程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# coding: utf-8
"""\
规则:
1. 中文分为数字(零、一、二、三、四、伍、六、七、八、九),数位[个、十、百、千、万、亿]和符号[负,点]三部分
2. 数位个略去
3. 以一十开头略去首位一
4. 数位为零,保留数字零略去该数位单位
5. 连续数位为零,保留一个零
6. 个,万,亿位为零,略去零
7.
"""
numbers = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
units = ["亿", "万", "千", "百", "十", ""]
def i2c(i, recursive=False):
if i < 0:
return '负'+i2c(abs(i))
if i == 0:
return "零"
elif i < pow(10, 4):
result = ""
for d, u in zip(str(i).zfill(4), units[2:]):
result += numbers[int(d)]+u if d != "0" else "零"
elif i < pow(10, 8):
wj, rest = divmod(i, pow(10, 4))
result = i2c(wj)+"万"+("零" if rest < pow(10, 3) else "")+i2c(rest, True)
else:
yi, rest = divmod(i, pow(10, 8))
result = i2c(yi)+"亿"+("零" if rest < pow(10, 7) else "")+i2c(rest, True)
result = "零".join(result.replace("零", " ").split())
return result[1:] if result.startswith('一十') and not recursive else result
def f2c(f):
if f == '':
f = '0'
return '点'+''.join(map(lambda d: numbers[int(d)], f))
def n2c(n):
nsplit = n.split('.')
i = int(nsplit[0]) if nsplit[0] else 0
if len(nsplit) == 1:
return i2c(i)
elif len(nsplit) == 2 and n != '.':
return i2c(i)+f2c(nsplit[1])
else:
raise ValueError
if __name__ == '__main__':
import sys
print(n2c(sys.argv[1]))

注释和共享

Hexo是一个比较火的博客框架(主观),然后我使用了其中的Tranquilpeak主题,但是发现写着写着发现,本来应该等宽的代码部分明显不是等宽的,然后就翻文档

Change global style

If you want to change font families, font size, sidebar color, things like that, take a look at source/_css/utils/_variables.scss file. This file contains global variables used in this theme. Build the theme after changes to see changes.

OK,接着翻源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Global settings
// --------------------------------------------
// Font families
$open-sans: 'Open Sans';
$open-sans-sans-serif: 'Open Sans', sans-serif;
$merriweather-serif: 'Merriweather', serif;
$menlo: Menlo;
$font-family-base: $open-sans-sans-serif;
$font-families: (
// base
'headings': $open-sans-sans-serif,
// components
'code': $menlo,
'caption': $merriweather-serif,
'image-gallery': $open-sans,
'post-header-cover': $merriweather-serif,
'post-meta': $open-sans-sans-serif,
'post-content': $merriweather-serif,
'post-excerpt-link': $open-sans-sans-serif,
'highlight': $menlo,
// layout
'sidebar': $open-sans-sans-serif
);

Menlo这个字体是mono space的呀,怎么显示不对呢,然后我注意到这么一段话:

Menlo是一个无衬线等宽字体,由Jim Lyles设计,首次出现于2009年8月上市的Mac OS X Snow Leopard系统内建字体之一。基于开源字体Bitstream Vera与自由版权字体DejaVu字体改良而来

什么?Mac OS X内建字体?那也就是说本穷用的Windows 10 Home应该是不会有咯。然后本穷就下载,安装,重启浏览器,OK,终于显示正确了。

总结

  • Web开发不得不考虑跨平台的问题,所以一定不能在字体这个地方栽跟头,不能说你用的Mac开发的你就用Menlo不管了,好歹加个备选的monospace。

  • issue给作者之后发现,问题已经被fix,但是还得等下个版本release才能见到。这又教导我,在issue之前最好好好搜一下已有的issue和pull request,已经有的问题不要重复开issue。

注释和共享

PEP 7

发布在 编程

介绍

本文提供Python的C实现的C代码的编码风格。Python代码的风格指南参见相关信息的PEP[1]

注意,规则有时也会被打破。两个打破特定规则的好的理由:

  1. 当遵循这个规则回事代码更少地可读,即使其他人依据此规则去阅读代码。
  2. 未保持和周围也打破规则的代码一致(也许是历史原因)–尽管有一个机会去清理别人的烂摊子(以真正的XP格式)

C方言

  • Python 3.6之前使用的是ANSI/ISO标准C(1989版标准)。这意味着(以及其他许多情况)所有的申明都必须在代码块顶部(不需要再函数的顶部)。
  • Python 3.6及之后的版本使用采用了部分C99特性的C89:
    • 标准整形在<stdint.h><inttypes.h>中。我们要求定宽的整形类型。
    • static inline函数
    • 指定初始化器(designated initializers),对类型定义特别好。
    • 混合申明
    • 布尔值
    • C++风格的行注释
      未来C99的特性可能会被添加到这个列表视编译器支持而定(主要是MSVC)。
  • 不要使用GCC拓展(例如,不要写没有行尾的反斜杠的多行字符串)
  • 所有的函数申明和定义必须使用完全原型(例如,指定所有参数的类型)
  • 永远不要使用C++风格的//一行注释
  • 在几种主要编译器(gcc,VC++,一些其他的)上没有警告

代码布局

  • 使用4个空格缩进并完全禁用tab。
  • 每行不得超过79个字符。如果这一条和前一条一起没有给你的代码足够的空间,那么你的代码就太复杂了–考虑使用子程序。
  • 函数定义格式:函数名在第1列,最外面的花括号在第一列,在本地变量申明之后留空行。
1
2
3
4
5
6
7
8
9
10
static int
extra_ivars(PyTypeObject *type, PyTypeObject *base)
{
int t_size = PyType_BASICSIZE(type);
int b_size = PyType_BASICSIZE(base);
assert(t_size >= b_size); /* type smaller than base! */
...
return 1;
}
  • 代码结构:在诸如iffor等关键词和接下来的左括号直接一个空格;在括号内没有空格;大括号被强烈推荐使用但可在C允许的情况下省略,并且它们应格式化成下面所示:
1
2
3
4
5
6
if (mro != NULL) {
...
}
else {
...
}
  • return语句不应有多余的括号:
    return Py_None; /* correct */
    return(Py_None); /* incorrect */

  • 函数和宏的调用风格:foo(a, b, c)–在左括号之前没有空格,在括号中没有空格,在逗号前没有空格,在每个逗号后一个空格。

  • 总是在赋值符号,布尔值和比较符两边加上括号,在表达式中使用了很多操作符,在最外面的(最低优先级)的两边加上空格。

  • 长行换行:如果可以,在最外层表达式的逗号后折行。总是保持缩进

    1
    2
    3
    PyErr_Format(PyExc_TypeError,
    "cannot create '%.100s' instances",
    type->tp_name);
  • 当你在长表达式的二元操作符处换行,这个操作符跟在前一行的行末,例如:

    1
    2
    3
    4
    if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 &&
    type->tp_dictoffset == b_size &&
    (size_t)t_size == b_size + sizeof(PyObject *))
    return 0; /* "Forgive" adding a __dict__ only */
  • 在函数、结构定义、函数的主要片段的前后留空行。

  • 注释放在它们描述的函数之前。

  • 所有的函数和全局变量申明为static,除非他们是发布的接口的一部分

  • 对于外部函数和变量,我们总是在“Include”文件夹中合适的头文件中声明,使用PyAPI_FUNC()宏,如:

    PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);

命名习惯

  • 公共函数使用Py前缀;永远不要给静态函数(使用Py前缀)。Py_前缀给全局服务例程如Py_FatalError;特定的服务组(例如特定对象类型API)使用长前缀例如字符串使用PyString_。

  • 公共函数和变量使用混合大小写以及下划线,例如这些:PyObject_GetAttrPy_BuildValuePyExc_TypeError

  • 偶尔的一个“内部”函数需要对加载器可见,对此我们使用_Py前缀,例如:_PyObject_Dump

  • 宏应该是混合大小写的前缀跟着大写,例如:PyString_AS_STRINGPy_PRINT_RAW

文档字符串

  • 对文档字符串使用PyDoc_STR()或者PyDoc_STRVAR()宏以获得无文档字符串地编译Python(./configure --without-doc-strings)。

    对于需要支持早于2.3版本Python的C代码,你可以在引入Python.h后包含如下:

    1
    2
    3
    4
    5
    #ifndef PyDoc_STR
    #define PyDoc_VAR(name) static char name[]
    #define PyDoc_STR(str) (str)
    #define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
    #endif
  • 函数文档字符串的第一行应是一个“签名行”–给出一个参数和返回值简短的概要,例如:

    1
    2
    3
    PyDoc_STRVAR(myfunction__doc__,
    "myfunction(name, value) -> bool\n\n\
    Determine whether name and value make a valid pair.");

    总是包含一个空行在签名行和描述的文本之间。

    如果函数的返回值总是为None(因为没有有意义的返回值),不要写返回类型的提示。

  • 当写多行文档字符串时,确保总是像上面例子中使用反斜杠继续,或者字符串字面相连:

    1
    2
    3
    PyDoc_STRVAR(myfunction__doc__,
    "myfunction(name, value) -> bool\n\n"
    "Determine whether name and value make a valid pair.");

    尽管一些C编译器接受没有上述两种规范的字符串:

    1
    2
    3
    4
    /* BAD -- don't do this! */
    PyDoc_STRVAR(myfunction__doc__,
    "myfunction(name, value) -> bool\n\n
    Determine whether name and value make a valid pair.");

    不要这么做;已知MSVC编译器会抱怨这个。

参考

[1] PEP 8 , “Style Guide for Python Code”, van Rossum, Warsaw ( http://www.python.org/dev/peps/pep-0008 )

版权信息

此文档已放在公共领域。

源:https://github.com/python/peps/blob/master/pep-0007.txt

注释和共享

Python源码学习笔记-0

发布在 编程

Python

0. 前言

年初的时候给自己挖了一个坑,计划要在今年过一遍Python的源码。结果这一年零零碎碎总有事情耽搁了。现在已经10月份了,再不填坑就来不及了。于是有了这个系列。

说到看Python源码,陈儒的Python源码剖析可谓经典了。本系列基本也是根据此书的结构的。不过此书出版已近十年(2016-10),Python版本也从2.5到了3.5。不才能力有限,姑妄言之。

运行环境:Bash on Ubuntu on Windows,同样适用其他于UNIX-like环境。

1. 获取Python源码

你可以选择2.7.123.5.2。当然你也可以使用hg clone https://hg.python.org/cpythonhg update 3.5这样的命令来选择你喜欢的版本分支。(hg通过sudo apt install mercurial安装)

值得注意的是,CPython会检测到是否是从工作拷贝(由hg clone的)运行。这意味着如果你在你的拷贝中编辑CPython源码,Python代码(.py文件)的改变会被解释器立即使用和测试。(如果你修改的是C代码,你将需要重新编译受影响的文件)。

2. 编译为调试模式

CPython提供几种编译flag帮助调试很多东西。所有已知的flag都可以在Misc/SpecialBuilds.txt文件中找到,最常用的是Py_DEBUG标志。

暂时还不清楚SpecialBuilds中的编译选项的具体用法,搞明白之后再更新。

构建debug版的Python,可以在源码根目录中运行./configure --with-debug

Python源码剖析中有提到--enable-shared,如果你不知道是干什么的建议不要加上,不然会链接到系统自带的Python的。

2.1. 构建依赖

CPython的核心解释器需要C编译器构建。一些拓展模块也依赖额外的库。
Debian/Ubuntu系的可执行如下命令安装依赖:
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \ libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils

Mac OS X:
brew install readline xz
其他发行版本参见参考资料[2]。

3. 目录结构

大部分的子文件夹都有自己的README。大部分的文件都有注释。

文件或文件夹 简介
Demo/ 示例脚本,模块和程序
Doc/ 文档源(reStructuredText)
Grammar/ Python的EBNF语法文件
Include/ 公共头文件
LICENSE 授权信息
Lib/ Python部分标准库,均是Python写的
Mac/ Macintosh特定的资源(例如,用IDLE作为OS X的应用)
Makefile.pre.in Source from which config.status creates the Makefile.pre
Misc/ 其他有用的文件
Modules/ 大部分内置模块的实现
Objects/ 大部分内置对象类型的实现
PC/ PC特定的文件(DOS, Windows, OS/2)
PCbuild/ Microsoft Visual C++的build目录
Parser/ 解析器和分词器以及他们的输入处理AST的节点也在这个文件夹
Python/ 字节编译器和解释器,Python核心部分。
README 读我
RISCOS/ RISC操作系统特定的文件
Tools/ 一些用Python写的有用的程序
pyconfig.h.in Source from which pyconfig.h is created (GNU autoheader output)
configure 配置的shell脚本(GNU autoconf的输出)
configure.ac 配置格式(GNU autoconf的输入)
install-sh 用来安装文件的Shell脚本

4. 贴士

4.1. Py_ssize_t
首先理解什么是size_t,然后是ssize_t,然后你就知道什么是Py_ssize_t了。
4.2. int_repr
在最新的Python代码中没有了int_repr这个函数,甚至没有了intobject。善用搜索引擎,发现了旧版本的intobject.c中有两处int_repr,一处是定义,一处是引用。(reprfunc)int_repr, /* tp_repr */拿注释tp_repr在新版里搜,发现了long_to_decimal_string, /* tp_repr */不出意外这就是改动后的函数,试试再按Python源码剖析的例子操作,成功输出。

未完待续

参考资料:

[1] Python Developer’s Guide — Python Developer’s Guide
[2] Common build problems · yyuu/pyenv Wiki

注释和共享

  • 第 1 页 共 1 页
作者的图片

唐梓涯

Pythoner, Emacser, GNU/Linuxer
目前在微软技术支持掏粪


全栈工程师


中国无锡