为什么从类中访问类变量需要“自我”。 在Python中?

可能重复:
Python'自我'解释

我正在学习Python,我有一个问题,比实际更理论,关于这个类的方法的访问类变量。

例如我们有:

class ExampleClass:
    x = 123
    def example_method(self):
        print(self.x)

为什么必须写出完全的self.x ,而不仅仅是xx属于类的名称空间,使用它的方法也属于它。 我错过了什么? 这种风格背后有什么理由?

在C ++中,您可以编写:

class ExampleClass {
public:
    int x;
    void example_method()
    {
        x = 123;
        cout << x;
    };
};

它会起作用!


从Python的历史:添加对用户定义类的支持:

相反,我决定放弃隐式引用实例变量的想法。 像C ++这样的语言可以让你编写this-> foo来显式地引用实例变量foo(万一有一个单独的局部变量foo)。 因此,我决定让这样的显式引用成为引用实例变量的唯一方法。 另外,我决定不是将当前对象(“t​​his”)作为特殊关键字,而是简单地将“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',官方文档称其为模块的名称空间。

    链接地址: http://www.djcxy.com/p/54729.html

    上一篇: Why accessing to class variable from within the class needs "self." in Python?

    下一篇: Matplotlib and GTKAgg and OS X