用于类定义的Python包生成导入函数

2024-09-26 18:07:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在构建一个python包,它基本上是请求包的包装器,旨在使对一组数据库的各种api调用变得更容易。你知道吗

当前,我的包具有以下目录结构:

package\
  - __init__.py
  - coreFunc.py
  subpackage\
    - __init__.py
    - mod1.py
    - mod2.py

包的主要功能在于mod1.pymod2.pymod1.py看起来像这样:

import requests as _requests
from package.coreFunc import __func1

class DataPull:
    def __init__(self, arg1):
      self._url = "http://www.somesite.com/info?"
      self._api_param = {'argument':__func1(arg1)}
      self._pull = _requests.get(self._url, params = self._api_param)
    def DataTableOne(self):
        _headers = self._pull.json()['resultSets'][0]['headers']
        _values = self._pull.json()['resultSets'][0]['rowSet']
        return [dict(zip(_headers, value)) for value in _values]
    def DataTableTwo(self):
        _headers = self._pull.json()['resultSets'][1]['headers']
        _values = self._pull.json()['resultSets'][1]['rowSet']
        return [dict(zip(_headers, value)) for value in _values]

coreFunc.py中,我有一些函数需要在mod1.pymod2.py中的特定类中使用。事实上,在类定义的第三行中,我使用在coreFunc中定义的函数(__func1)修改参数的用户输入,以确保将正确的值传递给api调用。你知道吗

你知道吗coreFunc.py公司看起来像这样:

def __func1(x):
    if str(x) == "1999":
    return "1999-00"
elif len(str(x)) == 4:
    try:
        return "-".join([str(x),str(int(x) % 100 + 1)])
    except: 
        raise Exception("Enter the four-digit year")
else: raise Exception("Enter the four-digit year")

我为这个调用使用一个类,因为调用会产生多个数据表,并且我使用方法来访问每个数据表。你知道吗

我的问题是,当我尝试创建DataPull类的对象时:

newObj = DataPull(argument)

显示以下错误:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-24-e3399cf393bd> in <module>()
----> 1 traceback.extract_stack(package.mode1.DataPull("203112"))

C:\Users\Bradley\Anaconda3\lib\site-packages\test-package-py3.4.egg\package\subpackage\mod1.py in __init__(self, arg1)
    140         self._url = "http://www.somesite.com/info?"
--> 141         self._api_param = {"Season":__func1(arg1)}

NameError: name '_DataPull__func1' is not defined

如何将__func1正确导入mod1.py以修复此错误?你知道吗


Tags: pyselfapijsonpackageinitdefpull
2条回答

函数前面有两个下划线意味着它是私有的。您可以将它重命名为_func1,它就可以工作了。你知道吗

或者,导入__func1,如下所示:

from package.coreFunc import __func1 as _func1

__init__中使用_func1而不是__func1。你知道吗

这是name mangling的一个例子,在类定义中,任何在它前面有__的东西都被更改为_classname__attr。引用文件:

Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

这是在源代码级别完成的,因此可以将类定义中要使用的函数名更改为其他名称,这样就可以正常工作。你知道吗


来自compile.c的相关CPython代码:

PyObject *
_Py_Mangle(PyObject *privateobj, PyObject *ident)
{
    /* Name mangling: __private becomes _classname__private.
       This is independent from how the name is used. */
    const char *p, *name = PyString_AsString(ident);
    char *buffer;
    size_t nlen, plen;
    if (privateobj == NULL || !PyString_Check(privateobj) ||
        name == NULL || name[0] != '_' || name[1] != '_') {
        Py_INCREF(ident);
        return ident;
    }
    p = PyString_AsString(privateobj);
    nlen = strlen(name);
    /* Don't mangle __id__ or names with dots.

       The only time a name with a dot can occur is when
       we are compiling an import statement that has a
       package name.

       TODO(jhylton): Decide whether we want to support
       mangling of the module name, e.g. __M.X.
    */
    if ((name[nlen-1] == '_' && name[nlen-2] == '_')
        || strchr(name, '.')) {
        Py_INCREF(ident);
        return ident; /* Don't mangle __whatever__ */
    }
    /* Strip leading underscores from class name */
    while (*p == '_')
        p++;
    if (*p == '\0') {
        Py_INCREF(ident);
        return ident; /* Don't mangle if class is just underscores */
    }
    plen = strlen(p);

    if (plen + nlen >= PY_SSIZE_T_MAX - 1) {
        PyErr_SetString(PyExc_OverflowError,
                        "private identifier too large to be mangled");
        return NULL;
    }

    ident = PyString_FromStringAndSize(NULL, 1 + nlen + plen);
    if (!ident)
        return 0;
    /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */
    buffer = PyString_AS_STRING(ident);
    buffer[0] = '_';
    strncpy(buffer+1, p, plen);
    strcpy(buffer+1+plen, name);
    return ident;
}

相关问题 更多 >

    热门问题