#584 Python 源码学习 06: tuple

2021-08-05

源码

INIT_TYPE(&PyTuple_Type, "tuple");
SETBUILTIN("tuple", &PyTuple_Type);

**cpython/Include/cpython/tupleobject.h**

typedef struct {
    PyObject_VAR_HEAD
    /* ob_item contains space for 'ob_size' elements.
       Items must normally not be NULL, except during construction when
       the tuple is not yet visible outside the function that builds it. */
    PyObject *ob_item[1];
} PyTupleObject;

当然,与之对应的 PyTypeObject PyTuple_Type 定义在 Objects/tupleobject.c,就不贴出来了。

PyTuple_SET_ITEM 似乎是在完成内存初始化的空间内填充元素时使用的。

成员方法

tuple 类型只有两个成员方法:count, index

#define TUPLE_INDEX_METHODDEF    \
    {"index", (PyCFunction)(void(*)(void))tuple_index, METH_FASTCALL, tuple_index__doc__},

#define TUPLE_COUNT_METHODDEF    \
    {"count", (PyCFunction)tuple_count, METH_O, tuple_count__doc__},

static PyMethodDef tuple_methods[] = {
    TUPLE___GETNEWARGS___METHODDEF
    TUPLE_INDEX_METHODDEF
    TUPLE_COUNT_METHODDEF
    {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
    {NULL,              NULL}           /* sentinel */
};

引用计数

Py_INCREF
Py_DECREF
Py_XINCREF
Py_XDECREF

#583 Git 命令

2021-08-04

看到有篇文章说是 git “新增”了 switch 和 restore 两个命令,仔细一看,原来就是 2019 年就引入了的两个命令,不过我确实没有用过。

这里重新整理一下现在 git 的命令。

git version
git version 2.30.2

apt list --installed | grep ^git
git-doc/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装]
git-extras/hirsute,hirsute,now 6.1.0-1 all [已安装]
git-flow/hirsute,hirsute,now 1.12.3-1 all [已安装]
git-man/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装,自动]
git-svn/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装]
git/hirsute,now 1:2.30.2-1ubuntu1 amd64 [已安装]
gitg/hirsute,now 3.32.1-1 amd64 [已安装]
gitk/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装]

#582 Beego 路由

2021-08-02

基础路由

web.Get(router, web.HandleFunc)
web.Post(router, web.HandleFunc)
web.Put(router, web.HandleFunc)
web.Patch(router, web.HandleFunc)
web.Head(router, web.HandleFunc)
web.Options(router, web.HandleFunc)
web.Delete(router, web.HandleFunc)
web.Any(router, web.HandleFunc)

控制器路由

// func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *HttpServer {
//  return BeeApp.Router(rootpath, c, mappingMethods...)
// }
beego.Router("/admin", &admin.UserController{})
  • 默认匹配 /:id, /?:id
  • 类型匹配 /:id:int, /:id:string
  • 正则匹配 /:id([0-9]+)
  • 星号匹配 /username/* => :splat 变量
    /username/*.* => :path 变量和 :ext 变量

取变量的方式:

c.Ctx.Input.Param(":id")

mappingMethods

映射 HTTP 方法到指定方法。

  1. 支持基础路由中提到到八种方法(Any 用星号代替,优先级最低)。
  2. 如果不指定这个参数,会映射 GET 请求到 Get 方法,以此类推。
  3. 应该不支持指定多个方法。
  4. 应该不支持重复指定方法。
web.Router("/api/food",&RestController{},"get:ListFood")
web.Router("/api/food",&RestController{},"post:CreateFood")
web.Router("/api/food",&RestController{},"put:UpdateFood")
web.Router("/api/food",&RestController{},"delete:DeleteFood")

web.Router("/api",&RestController{},"get,post:ApiFunc")

web.Router("/api/food",&RestController{},"get:ListFood;post:CreateFood;put:UpdateFood;delete:DeleteFood")

注意:控制器可以声明 URLMapping 方法,比 mapptingMethods 参数通过反射实现更加高效。

func (c *CMSController) URLMapping() {
    c.Mapping("StaticBlock", c.StaticBlock)
    c.Mapping("AllBlock", c.AllBlock)
}

自动路由

web.AutoRouter(&controllers.ObjectController{})

URL 采用 /:controller/:method 前缀的方式,后面的部分会转化成 map 参数 (.Ctx.Input.Params)。
method 不区分大小写,对应的处理方法名首字母大写,比如 login -> Login。

注意:/system/config.json 对应到 SystemController.Config 方法,后缀通过 .Ctx.Input.Param(":ext") 获取。

注解路由

  1. 2.0 开始支持,dev 模式生效
  2. 自动扫描指定目录,生成 routers/commentsRouter.go 文件
  3. CommentRouterPath 配置扫描目录
web.Include(&CMSController{})

相应的控制器需要添加这样格式的注解:

// @router /staticblock/:key [get]

#577 塔利班和阿富汗局势

2021-07-29

之前写过一片博客:《阅读:追风筝的人》, 了解了阿富汗的一些事情。

在抖音上看到:昨天阿塔(阿富汗塔利班)代表团来华访问,外长王毅负责接见。我方强调对 “东伊运” 的打击,塔利班也声明反对一切利用阿富汗从事危害中国的行为。
PS: 塔利班执政时期,阿富汗外交部曾经声明会保护祖先留下来的遗迹,没过几天,他们的领袖就下令炸毁巴米扬大佛。

从八十年代至今的几十年,中国都是维持中立,尽可能避免卷入别国政治风波。所以,从塔利班访华来看,应该是稳了。
希望塔利班这次执政能善待本国人民,同时和恐怖分子划清界限。

PS:塔利班曾经和东伊运有着密切的关系。

PS: 注意阿塔和巴塔之间的分别。引用 7/19 外交部例行记者会上赵立坚的发言:

你关于 “巴基斯坦塔利班” 和阿富汗塔利班的认识是客观的,两者是不一样的。“巴基斯坦塔利班” 是巴基斯坦政府和国际社会普遍认定的恐怖组织,其承认参与制造了包括奎达酒店爆炸在内的多起恐怖袭击。阿富汗塔利班称自己是一个政治、军事组织,公开表示禁止任何组织或个人利用阿富汗领土威胁其他国家,近年同阿富汗政府和国际社会保持着对话接触。

PS: 7/14 巴基斯坦汽车爆炸事件,多名中巴人员伤亡,网上很多人认为是巴塔针对中国人发起的恐怖袭击。

#576 特殊号码

2021-07-28

*#06# 移动设备识别码

弹出一个框,title 是 “移动设备识别码”:

MEID :14 位数字
IMEI1: 15 位数字
IMEI2: 15 位数字
  • MEID, Mobile Equipment Identifier, 移动设备识别码

    移动设备识别码是一个全球唯一的识别 CDMA2000 移动台设备的号码。该号码的格式由 3GPP2 report S.R0048 定义,不过可以看作一个使用十六进制数字的IMEI。

  • IMEI, International Mobile Equipment Identity, 国际移动设备识别码

    通常所说的手机 “串号”,用于在移动电话网络中识别每一部独立的手机等移动通信设备,相当于移动电话的身份证。序列号共有15位数字,前6位(TAC)是型号核准号码,代表手机类型。接着2位(FAC)是最后装配号,代表产地。后6位(SNR)是串号,代表生产顺序号。最后1位(SP)一般为0,是检验码,备用。国际移动设备识别码一般贴于机身背面与外包装上,同时也存在于手机存储器中,通过输入 *#06# 即可查询。

*#*#4636#*#* 小米手机测试信息

三个子菜单:

  • 手机信息1
  • 手机信息2
  • WLAN infomation

#575 Python 源码学习 05: strbytes

2021-07-28

有了 int 的一点点经验,先找:

SETBUILTIN("bytearray",             &PyByteArray_Type);
SETBUILTIN("bytes",                 &PyBytes_Type);
SETBUILTIN("str",                   &PyUnicode_Type);

INIT_TYPE(&PyByteArray_Type, "bytearray");
INIT_TYPE(&PyBytes_Type, "str");
INIT_TYPE(&PyUnicode_Type, "str");

PS: 而且还可以通过 bytes 类型的 __doc__ 内容在 cpython 源码中搜索。
PS: 这里有一个奇怪的地方,就是 INIT_TYPE 的时候,把 PyBytes_Type 给了 str

PyBytes_Type

Objects/bytesobject.c

PyTypeObject PyBytes_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "bytes",
    PyBytesObject_SIZE,
    sizeof(char),
    0,                                          /* tp_dealloc */
    0,                                          /* tp_vectorcall_offset */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                          /* tp_as_async */
    (reprfunc)bytes_repr,                       /* tp_repr */
    &bytes_as_number,                           /* tp_as_number */
    &bytes_as_sequence,                         /* tp_as_sequence */
    &bytes_as_mapping,                          /* tp_as_mapping */
    (hashfunc)bytes_hash,                       /* tp_hash */
    0,                                          /* tp_call */
    bytes_str,                                  /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    &bytes_as_buffer,                           /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
        Py_TPFLAGS_BYTES_SUBCLASS,              /* tp_flags */
    bytes_doc,                                  /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    (richcmpfunc)bytes_richcompare,             /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    bytes_iter,                                 /* tp_iter */
    0,                                          /* tp_iternext */
    bytes_methods,                              /* tp_methods */
    0,                                          /* tp_members */
    0,                                          /* tp_getset */
    &PyBaseObject_Type,                         /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    bytes_new,                                  /* tp_new */
    PyObject_Del,                               /* tp_free */
};
typedef struct {
    PyObject_VAR_HEAD
    Py_hash_t ob_shash;
    char ob_sval[1];

    /* Invariants:
     *     ob_sval contains space for 'ob_size+1' elements.
     *     ob_sval[ob_size] == 0.
     *     ob_shash is the hash of the string or -1 if not computed yet.
     */
} PyBytesObject;

我不知道这个 PyBytesObject 是个啥。
回头找 int 相关信息,果然找到 typedef struct _longobject PyLongObject;
就在网上搜索,结果找到 python 官网(Bytes Objects)有相关信息:

PyBytesObject

This subtype of PyObject represents a Python bytes object.

PyTypeObject PyBytes_Type

This instance of PyTypeObject represents the Python bytes type; it is the same object as bytes in the Python layer.

PyUnicode_Type

Objects/unicodeobject.c

PyTypeObject PyUnicode_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "str",                        /* tp_name */
    sizeof(PyUnicodeObject),      /* tp_basicsize */
    0,                            /* tp_itemsize */
    /* Slots */
    (destructor)unicode_dealloc,  /* tp_dealloc */
    0,                            /* tp_vectorcall_offset */
    0,                            /* tp_getattr */
    0,                            /* tp_setattr */
    0,                            /* tp_as_async */
    unicode_repr,                 /* tp_repr */
    &unicode_as_number,           /* tp_as_number */
    &unicode_as_sequence,         /* tp_as_sequence */
    &unicode_as_mapping,          /* tp_as_mapping */
    (hashfunc) unicode_hash,      /* tp_hash*/
    0,                            /* tp_call*/
    (reprfunc) unicode_str,       /* tp_str */
    PyObject_GenericGetAttr,      /* tp_getattro */
    0,                            /* tp_setattro */
    0,                            /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
    Py_TPFLAGS_UNICODE_SUBCLASS,   /* tp_flags */
    unicode_doc,                  /* tp_doc */
    0,                            /* tp_traverse */
    0,                            /* tp_clear */
    PyUnicode_RichCompare,        /* tp_richcompare */
    0,                            /* tp_weaklistoffset */
    unicode_iter,                 /* tp_iter */
    0,                            /* tp_iternext */
    unicode_methods,              /* tp_methods */
    0,                            /* tp_members */
    0,                            /* tp_getset */
    &PyBaseObject_Type,           /* tp_base */
    0,                            /* tp_dict */
    0,                            /* tp_descr_get */
    0,                            /* tp_descr_set */
    0,                            /* tp_dictoffset */
    0,                            /* tp_init */
    0,                            /* tp_alloc */
    unicode_new,                  /* tp_new */
    PyObject_Del,                 /* tp_free */
};

字符串格式化

我想找 % 格式化,{} 格式化,以及最新的 fstring 的实现方式,但是代码的复杂性,让我在预计的时间之内无法完成,只好到此打住。

可能得从 parse.cast.c 语法树开始,再到 parse_string.c

// Objects/unicodeobject.c
// PyMethodDef unicode_methods 中的几行:
{"format", (PyCFunction)(void(*)(void)) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},
{"format_map", (PyCFunction) do_string_format_map, METH_O, format_map__doc__},
UNICODE___FORMAT___METHODDEF

// Objects/clinic/unicodeobject.c.h
#define UNICODE___FORMAT___METHODDEF    \
    {"__format__", (PyCFunction)unicode___format__, METH_O, unicode___format____doc__},

static PyObject *
unicode___format__(PyObject *self, PyObject *arg)
{
    PyObject *return_value = NULL;
    PyObject *format_spec;

    if (!PyUnicode_Check(arg)) {
        _PyArg_BadArgument("__format__", "argument", "str", arg);
        goto exit;
    }
    if (PyUnicode_READY(arg) == -1) {
        goto exit;
    }
    format_spec = arg;
    return_value = unicode___format___impl(self, format_spec);

exit:
    return return_value;
}
static PyObject *
do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
{
    SubString input;

    /* PEP 3101 says only 2 levels, so that
       "{0:{1}}".format('abc', 's')            # works
       "{0:{1:{2}}}".format('abc', 's', '')    # fails
    */
    int recursion_depth = 2;

    AutoNumber auto_number;

    if (PyUnicode_READY(self) == -1)
        return NULL;

    AutoNumber_Init(&auto_number);
    SubString_init(&input, self, 0, PyUnicode_GET_LENGTH(self));
    return build_string(&input, args, kwargs, recursion_depth, &auto_number);
}

static PyObject *
do_string_format_map(PyObject *self, PyObject *obj)
{
    return do_string_format(self, NULL, obj);
}

没啥头绪,放弃。