为什么从类中访问类变量需要“自我”。 在Python中?
可能重复:
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 ++这样的语言可以让你编写this-> foo来显式地引用实例变量foo(万一有一个单独的局部变量foo)。 因此,我决定让这样的显式引用成为引用实例变量的唯一方法。 另外,我决定不是将当前对象(“this”)作为特殊关键字,而是简单地将“this”(或其等价物)作为方法的第一个命名参数。 实例变量总是被引用为该参数的属性。
使用明确的引用,不需要为方法定义提供特殊的语法,也不必担心有关变量查找的复杂语义。 相反,只需定义一个函数,其第一个参数对应于实例,按惯例命名为“self”。 例如:
def spam(self,y):
print self.x, y
这种方法类似于我在Modula-3中看到的,它已经为我提供了导入和异常处理的语法。 Modula-3没有类,但它可以让你创建包含完全类型化的函数指针成员的记录类型,默认情况下它们被初始化为附近定义的函数,并添加语法糖,以便如果x是这样的记录变量,并且m是该记录的函数指针成员,初始化为函数f,然后调用xm(args)相当于调用f(x,args)。 这与对象和方法的典型实现相匹配,并且可以将实例变量与第一个参数的属性等同起来。
所以,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
以下是我在古代有关此功能的答案中所做的内容:
您遇到的问题是由于:
块是作为一个单元执行的一段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
它让我想知道在方法tell()
写入的指令print COLOR
如何激发打印在类外定义的全局对象COLOR的值。
我在官方文档的这一部分找到了答案:
方法可以像普通函数一样引用全局名称。 与方法关联的全局范围是包含其定义的模块。 (一个类永远不会被用作全局范围。)虽然很少有人在方法中使用全局数据,但全局范围有许多合法用途:首先,导入全局范围的函数和模块可以被方法使用,以及在其中定义的函数和类。 通常,包含该方法的类本身在全局范围内定义(...)
http://docs.python.org/2/tutorial/classes.html#method-objects
当解释器必须执行print self.COLOR
,由于COLOR不是实例属性(也就是说,标识符'COLOR'不属于实例的名称空间),解释器将进入类的名称空间的实例中搜索标识符'COLOR'并找到它,因此它会打印出TellColor.COLOR的值
当解释器必须执行print COLOR
,由于在该指令中没有写入属性访问,它将在全局名称空间中搜索标识符'COLOR',官方文档称其为模块的名称空间。
上一篇: Why accessing to class variable from within the class needs "self." in Python?