在 Python 的编码世界中,命名域是一个很重要的概念。惯常来说,我们常常会要求代码中尽量不要出现重复的变量名或函数名,但让人猝不及防的是,我们 import 的 package 中含有大量的函数名,我们并不能很轻易的避免这个问题。故而,常会遇到命名域冲突的问题。
在Python 的命名域机制中,可以认为存在两个命名域层,一个是 global 层,一个是 local 层。打个比方,当代码运行中遇到了变量/函数 X,那么 Python 会先在 local 层中寻找名字叫做 X 的变量/函数。因为在 Python 中,函数名也可以当做一个可以被传递的变量,故而我们之后统称为变量。当 local 层中存在 X 变量时,程序会自动的使用这个 local 的 X 代表的变量。如果 local 层中没有 X 的名字存在,那么 Python 会向上到 global 层中寻找。那么当 local 和 global 层都存在一个叫做 X 的变量怎么办?Python 的机制是如果 local 中的变量名和 global 中的变量名重复,则对 global 中的变量名进行遮蔽。也就是说,如果不在代码中加以说明进行区分的话,系统自动调用的是 local 层中的变量,而不会是 global。
这两天在搞的 alphabase.ai 的比赛就遇到了这样的问题,很坑爹。因为比赛方提供的数据是CSV文档,用 Python 打开的是 Pandas 的 DataFrame 格式的数据,然后我又想用 liblinear 包来解决这个 classification 的问题。在跑代码的时候就老是出现
TypeError 'DataFrame' object is not callable
这个情况,很烦,一开始还以为是数据没有洗干净,从 DataFrame 到 list 的转换过程不干净,就先从 DataFrame 转到了 Numpy. ndarry,在从 ndarry 转到 list. list() 和 np.tolist() 都试过了,还是报错,完全不知道错在哪里。。。直到看了一篇 Stack Overflow 的答案之后才明白。。原来是重名了。。。 话不多述,详细讲讲:
import pandas as pd
import numpy as np
import pandas as pd
import numpy as np
from svmutil import *
这是 import 部分,接下来:
X_train = pd.read_csv('train.csv', header=0)
X_test = pd.read_csv('test.csv', header=0)
Y = train['Target']
train = np.array(train)[:, :55]
ID = test['ID']
test = np.array(test)[:, 1:56]
'''
省略若干
'''
m = train(prob_train, param)
报错,TypeError 'DataFrame' object is not callable。。。?????????
仔细检查才发现。。。原来是。。。因为。。。我的
m = train(prob_train, param)
这句话里有一个 train,而前面变量里也有一个 train。。。import 的 package 里面的变量都在 global 层,被 local 层的这个 DataFrame 的 train 遮蔽了。。。自动调用的是这个 DataFrame 类型的变量。。。所以相当于我干了这么个事儿:
m = pd.DataFrame(prob_train, param)
不报错才怪呢。。