Python源码学习之初始化(二)

在初始化中,调用
void
_Py_ReadyTypes(void)
{
    if (PyType_Ready(&PyType_Type) < 0)
        Py_FatalError("Can't initialize type type");

    if (PyType_Ready(&_PyWeakref_RefType) < 0)
        Py_FatalError("Can't initialize weakref type");
	...
}
对各种数据类型的定义做初始化

来看
int PyType_Ready(PyTypeObject *type)的定义,
它把传入的type的tp_base用&PyBaseObject_Type初始化

	...
    /* Initialize tp_base (defaults to BaseObject unless that's us) */
    base = type->tp_base;
    if (base == NULL && type != &PyBaseObject_Type) {
        base = type->tp_base = &PyBaseObject_Type;
        Py_INCREF(base);
    }

    /* Now the only way base can still be NULL is if type is
     * &PyBaseObject_Type.
     */

    /* Initialize the base class */
    if (base != NULL && base->tp_dict == NULL) {
        if (PyType_Ready(base) < 0)   //有点递归的意思
            goto error;
    }
	...
	
	
接着初始化其他成员变量

    /* Initialize tp_bases */
    bases = type->tp_bases;
    if (bases == NULL) {
        if (base == NULL)
            bases = PyTuple_New(0);
        else
            bases = PyTuple_Pack(1, base);
        if (bases == NULL)
            goto error;
        type->tp_bases = bases;
    }

    /* Initialize tp_dict */
    dict = type->tp_dict;
    if (dict == NULL) {
        dict = PyDict_New();
        if (dict == NULL)
            goto error;
        type->tp_dict = dict;
    }
	
接着是一些内置function的初始化

	/* Add type-specific descriptors to tp_dict */
    if (add_operators(type) < 0)
        goto error;
    if (type->tp_methods != NULL) {
        if (add_methods(type, type->tp_methods) < 0)
            goto error;
    }
    if (type->tp_members != NULL) {
        if (add_members(type, type->tp_members) < 0)
            goto error;
    }
	
这里重点看一下add_operators in typeobject.c

static int
add_operators(PyTypeObject *type)
{
	...
    init_slotdefs();
	...
}

/* Initialize the slotdefs table by adding interned string objects for the
   names and sorting the entries. */
static void
init_slotdefs(void)
{
    slotdef *p;
    static int initialized = 0;

    if (initialized)
        return;
    for (p = slotdefs; p->name; p++) {
        p->name_strobj = PyUnicode_InternFromString(p->name);
        if (!p->name_strobj)
            Py_FatalError("Out of memory interning slotdef names");
    }
    qsort((void *)slotdefs, (size_t)(p-slotdefs), sizeof(slotdef),
          slotdef_cmp);
    initialized = 1;
}

//这里是我们在python编程中经常重载的一些函数的列表
static slotdef slotdefs[] = {
    SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
           "x.__len__() <==> len(x)"),
    SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,
      "x.__add__(y) <==> x+y"),
    SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,
           "x.__getitem__(y) <==> x[y]"),
	...
}

    SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
           "x.__len__() <==> len(x)")
	
	#define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
    ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC)
	
	等价
	ETSLOT("__len__", as_sequence.sq_length, slot_sq_length, wrap_lenfunc, "x.__len__() <==> len(x)")
	
	#define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
    {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
     PyDoc_STR(DOC)}
	 
	等价
	
	{"__len__", offsetof(PyHeapTypeObject, as_sequence.sq_length), (void*)slot_sq_length, wrap_lenfunc, PyDoc_STR("x.__len__() <==> len(x)")}
	
	而
	typedef struct wrapperbase slotdef;
	struct wrapperbase {
    char *name;
    int offset;
    void *function;
    wrapperfunc wrapper;
    char *doc;
    int flags;
    PyObject *name_strobj;
	};
	
	
	于是上面的宏定义展开为
	{	"__len__",    /* name */
		offsetof(PyHeapTypeObject,  /* offset* /
		as_sequence.sq_length),  
		(void*)slot_sq_length, 		/* void *function */
		wrap_lenfunc,      /* wrapper */
		PyDoc_STR("x.__len__() <==> len(x)") /* char *doc */
	}
	
新建一个module的时候,总会调用,而
PyDict_SetItemString(m->md_dict, "__name__", nameobj)  这个函数会向字典里面加一个item,
于是我们可以在python启动以后写 xxxx.__name__,  xxx.__doc__
PyObject *
PyModule_New(const char *name)
{
    PyModuleObject *m;
    PyObject *nameobj;
    m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
    if (m == NULL)
        return NULL;
    m->md_def = NULL;
    m->md_state = NULL;
    nameobj = PyUnicode_FromString(name);
    m->md_dict = PyDict_New();
    if (m->md_dict == NULL || nameobj == NULL)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__package__", Py_None) != 0)
        goto fail;
    Py_DECREF(nameobj);
    PyObject_GC_Track(m);
    return (PyObject *)m;

 fail:
    Py_XDECREF(nameobj);
    Py_DECREF(m);
    return NULL;
}

当我们在命令行输入任何command的时候,都会调用pythonrun.c
int
PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
在PyTypeObject初始化中,add_xxxx 是操作该object的tp_dict,把每一个operator, method,member定义都以key-value的形势放到tp_dict里面
	if (add_operators(type) < 0)
        goto error;
    if (type->tp_methods != NULL) {
        if (add_methods(type, type->tp_methods) < 0)
            goto error;
    }
    if (type->tp_members != NULL) {
        if (add_members(type, type->tp_members) < 0)
            goto error;
    }
    if (type->tp_getset != NULL) {
        if (add_getset(type, type->tp_getset) < 0)
            goto error;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
K均值聚类算法是一种常用的无监督学习算法,用于将样本数据划分为K个不同的簇。以下是一个使用Python编写的K均值算法的简单源码示例: ```python import numpy as np def kmeans(data, K, max_iters=100): # 随机初始化质心 centroids = data[np.random.choice(len(data), K, replace=False), :] for _ in range(max_iters): # 分配样本到最近的质心 distances = np.linalg.norm(data[:, np.newaxis] - centroids, axis=2) cluster_assignment = np.argmin(distances, axis=1) # 更新质心 new_centroids = np.zeros_like(centroids) for i in range(K): new_centroids[i] = np.mean(data[cluster_assignment == i], axis=0) # 判断是否收敛 if np.all(centroids == new_centroids): break centroids = new_centroids return centroids, cluster_assignment # 测试 data = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]) K = 2 centroids, cluster_assignment = kmeans(data, K) print("质心:") print(centroids) print("样本分配结果:") print(cluster_assignment) ``` 上述源码实现了K均值算法的基本步骤。首先随机初始化K个质心,然后重复以下过程直到收敛。首先计算每个样本与质心的距离,将样本分配到最近的质心,并根据分配结果更新质心。最后,返回最终的质心和样本的分配结果。 在代码中,我们使用了numpy库进行向量化运算,提高了代码的效率。测试部分使用了一个简单的维样本数据集,并打印了最终的质心和样本的分配结果。 注意,上述代码只是一个简单的示例,实际应用中可能需要根据具体问题进行适当的调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值