Python 包构建 - 导入函数以在类定义中使用

标签 python class

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

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

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

该包的主要功能位于 mod1.pymod2.py 中。 mod1.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 来修复此错误?

最佳答案

这是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;
}

关于Python 包构建 - 导入函数以在类定义中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31465362/

相关文章:

python - Python 中的 3D 数据插值

python - Pandas :DataFrame.unstack 错误

python - 当 SqlAlchemy 中的列上有默认设置时,将列的值显式设置为 NULL

python - 根据不同数据框中的匹配值将摘要列添加到 Pandas 数据框中

C++类与函数,构造函数中的引用参数

python - pytest 传递数据进行清理

class - VBA 给出的方法或数据成员未找到我定义的方法

php静态属性

c++ - 用户定义的类(c++)是否有默认的显式转换函数?

class - "unresolved implicit call to super constructor"在 Dart 语言中是什么意思?