理解 PyDict_Check 的行为

3 投票
1 回答
971 浏览
提问于 2025-04-17 14:48

我最近在玩Python的C接口,觉得挺有意思的。不过今天遇到了一些问题。我有一个Python扩展,它里面有一个函数,期望接收一个或两个字典作为参数。我有点担心自己可能搞错了PyDict_CheckPyArg_ParseTuple的用法。下面是一个简单的例子:

static PyObject * doStuffToOtherStuff(MyCustomPyObject *self, PyObject *args) {
  char const *fmt = "OO";
  PyObject dict1, dict2;

  if (!PyArg_ParseTuple(args, fmt, &dict1, &dict2))
    return NULL;

  int hasDict1 = PyDict_Check(&dict1);
  int hasDict2 = PyDict_Check(&dict2);

  printf("%d %d\n");

  Py_INCREF(Py_None);
  return Py_None;
}

当我编译并导入这个扩展后,我这样调用它:

myClass.doStuffToOtherStuff(dict(), None)

我本来期待它打印出 1 0 ,但实际上它打印的是 1 1 。而且像这样调用也一样: myClass.doStuffToOtherStuff(None, None) myClass.doStuffToOtherStuff(None, dict()) myClass.doStuffToOtherStuff({}, None) #等等...

如果我把PyDict_Check改成PyDict_CheckExact,无论我传什么参数,它都会打印0 0

如果有人能给点建议,我会非常感激。

1 个回答

1

PyArg_ParseTuple 函数在处理 O 参数时,需要一个指向 PyObject * 的指针,而不是指向 PyObject 的指针。也就是说,传入的参数类型应该是 PyObject **

所以你的代码应该是:

  char const *fmt = "OO";
  PyObject *dict1, *dict2;

  if (!PyArg_ParseTuple(args, fmt, &dict1, &dict2))
    return NULL;

  int hasDict1 = PyDict_Check(dict1);
  int hasDict2 = PyDict_Check(dict2);

  // ...

撰写回答