我正在构建一个python包,它基本上是请求包的包装器,旨在简化对一组数据库的各种api调用。
目前,我的包具有以下目录结构:
package\
- __init__.py
- coreFunc.py
subpackage\
- __init__.py
- mod1.py
- mod2.py
该软件包的主要功能在于mod1.py
和mod2.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.py
和mod2.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以修复此错误?
答案 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
。