可能重复:
Python的“自我”解释
我正在学习Python和我有一个问题,理论多于实际,就从这个类的方法访问类变量。
例如,我们有:
class ExampleClass:
x = 123
def example_method(self):
print(self.x)
为什么一定要写明self.x
,不只是x
? x
属于的类的名称空间,方法,使用它属于它。 我在想什么? 什么理由站在这样的风格背后?
在C ++中,你可以这样写:
class ExampleClass {
public:
int x;
void example_method()
{
x = 123;
cout << x;
};
};
而且它的工作!
从Python中的历史:对于用户定义的类添加支持 :
相反,我决定放弃对实例变量含蓄地提及的想法。 像C ++语言让你写这 - >富显式引用实例变量foo的(如果有一个独立的局部变量foo的)。 因此,我决定做这样明确的引用来引用实例变量的唯一途径。 另外,我决定,而不是让当前对象(“本”)一个特殊的关键字,我只想做“这个”(同等或)第一个命名参数的方法。 实例变量也只是总是像这样的说法的属性被引用。
有了明确的参考,也没有必要对方法定义的特殊语法也不必担心有关变量查找复杂的语义。 相反,一个简单的定义,其第一个参数对应实例,其按照惯例被命名为功能“自我”。 例如:
def spam(self,y): print self.x, y
这种方法类似于东西我在Modula-3语言看出,其已经与语法进口和异常处理提供了我。 Modula-3语言没有类,但它可以让你创建一个包含完整类型函数指针成员记录类型的默认初始化到附近的定义的功能,并增加了语法糖,这样,如果x是这样一个记录变量,m是一个该记录,初始化为函数f,则调用XM(参数)的函数指针构件是相当于调用F(X,参数)。 这符合对象和方法的典型实现,而且很可能等同于实例变量的第一个参数的属性。
因此,由BDFL自己说,他决定用在隐自我明确自己唯一的真正原因是:
- 它是明确的
- 它是更容易实现,因为查询必须在运行时完成(而不是像在其他语言的编译时间),并具有自我暗示可能增加了查询的复杂性(因此成本)。
编辑:还有在Python的答案回答问题 。
这似乎与模块类范围的处理,在Python有关:
COLOR = 'blue'
class TellColor(object):
COLOR = 'red'
def tell(self):
print self.COLOR # references class variable
print COLOR # references module variable
a = TellColor()
a.tell()
> red
> blue
下面是我在做的内容古代回答关于此功能:
你遇到的问题是由于这样的:
A嵌段是作为一个单元执行的片Python程序文本。 以下是块:一个模块,功能体,和一个类定义。
(......)
范围定义一个块内的名称的可见性。
(......)
在类块定义名称的范围被限制在类块; 它不延伸到的方法的代码块 - 这包括生成器表达式,因为它们使用的是功能范围实施。 这意味着以下将失败:
A类:
a = 42 b = list(a + i for i in range(10))
http://docs.python.org/reference/executionmodel.html#naming-and-binding
上述装置:一个功能体是代码块和一个方法是一个函数,然后限定了存在于类定义中的功能体的名称不延伸到功能体。
这似乎很奇怪,我,我正在读这个的时候,但这是Python是如何制作的:
在类块定义名称的范围被限制在类块; 它不延伸到的方法的代码块
这是官方文档,说这个。
。
编辑
heltonbiker写了一个有趣的代码:
COLOR = 'blue'
class TellColor(object):
COLOR = 'red'
def tell(self):
print self.COLOR # references class variable
print COLOR # references module variable
a = TellColor()
a.tell()
> red
> blue
这让我不知道该怎么指令print COLOR
的方法里面写tell()
引发的类外定义全局对象颜色值的打印。
我发现在正式文件的这一部分的答案:
方法可以以同样的方式作为普通函数引用全局名称。 与方法相关联的全局范围是包含在其定义的模块。 (。一类是从未使用过作为全球范围内)尽管很少遇到一个很好的理由,在方法中使用全局数据,有全球范围内的许多合法的用途:其一,进口到全球范围内的功能和模块可以通过方法,以及函数和类在其中定义来使用。 通常,包含此方法的类本身在这个全球范围内定义(...)
http://docs.python.org/2/tutorial/classes.html#method-objects
当解释器来执行print self.COLOR
, 颜色不是一个实例属性(也就是标识符“COLOR”不属于实例的命名空间),解释云在类的命名空间在搜索标识符“COLOR”的实例和找到它,所以它打印TellColor.COLOR的价值
当解释器来执行print COLOR
,因为有写在该指令没有属性的访问,它将搜索全局命名空间中的标识符“COLOR”,其官方文档说,这是模块的名字空间。
什么属性名被附加到一个对象(和它的类,而这个类的祖先)在编译时不可判定。 所以,你要么使属性查找明确,或者你:
- 消除局部变量(在方法)和总是使用实例变量。 这并没有好处,因为它本质上消除他们所有的优势(至少在方法)的局部变量。
- 决定一个基地是否
x
是指属性或本地运行时(有一些额外的规则来决定何时x = ...
增加了一个新的属性,如果没有self.x
)。 这使得代码的可读性,因为你永远不知道哪一个名字应该是,在所有的方法每个局部变量基本上变成了公共接口的一部分(如安装该名称的属性改变方法的行为)。
双方都有附加的缺点,他们需要特殊的方法外壳。 眼下,一种“方法”只是一个普通的功能恰好是通过类属性进行访问。 这是一个广泛的使用良好的情况下非常有用的。
文章来源: Why accessing to class variable from within the class needs “self.” in Python? [duplicate]