Python包构建 - 用于类定义的导入函数

时间:2015-07-16 22:07:12

标签: python class

我正在构建一个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中的特定类中使用一些函数。实际上,在Class定义的第三行中,我使用__func1中定义的函数(coreFunc)来修改对参数的用户输入,以确保将正确的值传递给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以修复此错误?

2 个答案:

答案 0 :(得分:3)

这是name mangling的情况,类定义中前面带有__的任何内容都更改为_classname__attr。引自文档:

  

__spam形式的任何标识符(至少两个主要下划线,   最多一个尾随下划线)在文本上被替换为   _classname__spam,其中classname是当前的类名   剥离前导下划线。这种破坏是不加考虑的   到标识符的句法位置,只要它发生   在一个类的定义内。

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

来自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;
}

答案 1 :(得分:0)

在函数之前有两个下划线表示它是私有的。您可以将其重命名为% run k-means using the first points of all measure as the initial points idxK = kmeans(projData,nSignals, 'Start', projData(1:nSignals, :)); figure(3); liColors = [{'yx'},{'mx'},{'cx'},{'bx'},{'kx'},{'gx'},{'rx'},{'gd'}]; for k = 1:nSignals plot(projData(idxK==k,1), projData(idxK==k,2), liColors{k}), hold on; end ,然后就可以了。

或者,按如下方式导入% plot results on original data figure(4); for k = 1:nSignals plot(projData(idxK==k,1), liColors{k}), hold on; end

_func1

__func1中使用from package.coreFunc import __func1 as _func1 代替_func1