Why accessing to class variable from within the class needs “self.” in Python?
Possible Duplicate:
Python ‘self’ explained
我正在学习python,我有一个关于从这个类的方法中访问类变量的问题,这是理论上的,而不是实际的。
例如,我们有:
1 2 3 4 | class ExampleClass: x = 123 def example_method(self): print(self.x) |
为什么一定要写准确的
在C++中你可以写:
1 2 3 4 5 6 7 8 9 | class ExampleClass { public: int x; void example_method() { x = 123; cout << x; }; }; |
它会起作用的!
从python的历史记录:添加对用户定义类的支持:
Instead, I decided to give up on the idea of implicit references to
instance variables. Languages like C++ let you write this->foo to
explicitly reference the instance variable foo (in case there’s a
separate local variable foo). Thus, I decided to make such explicit
references the only way to reference instance variables. In addition,
I decided that rather than making the current object ("this") a
special keyword, I would simply make"this" (or its equivalent) the
first named argument to a method. Instance variables would just always
be referenced as attributes of that argument.With explicit references, there is no need to have a special syntax
for method definitions nor do you have to worry about complicated
semantics concerning variable lookup. Instead, one simply defines a
function whose first argument corresponds to the instance, which by
convention is named"self." For example:
1
2 def spam(self,y):
print self.x, yThis approach resembles something I had seen in Modula-3, which had
already provided me with the syntax for import and exception handling.
Modula-3 doesn’t have classes, but it lets you create record types
containing fully typed function pointer members that are initialized
by default to functions defined nearby, and adds syntactic sugar so
that if x is such a record variable, and m is a function pointer
member of that record, initialized to function f, then calling
x.m(args) is equivalent to calling f(x, args). This matches the
typical implementation of objects and methods, and makes it possible
to equate instance variables with attributes of the first argument.
因此,在BDFL本人的陈述中,他决定使用显性自我而非隐性自我的唯一真正原因是:
- 它是明确的
- 更容易实现,因为查找必须在运行时完成(而不是像其他语言那样在编译时完成),并且具有隐式的self可能会增加查找的复杂性(从而增加查找的成本)。
编辑:在python常见问题解答中也有一个答案。
以下是我在一个关于这个特征的古老答案中所做的内容:
您遇到的问题是由以下原因造成的:
A block is a piece of Python program text that is executed as a unit.
The following are blocks: a module, a function body, and a class
definition.(...)
A scope defines the visibility of a name within a
block.(...)
The scope of names defined in a class block is limited to
the class block; it does not extend to the code blocks of methods –
this includes generator expressions since they are implemented using a
function scope. This means that the following will fail:class A:
1
2
3 a = 42
b = list(a + i for i in range(10))http://docs.python.org/reference/executionmodel.html#naming-and-binding
以上是指:函数体是一个代码块,方法是一个函数,那么在类定义中存在的函数体之外定义的名称不会扩展到函数体。
当我读到这篇文章时,我觉得很奇怪,但这就是Python的制作方法:
类块中定义的名称范围仅限于类块;它不扩展到方法的代码块。这是官方文件。
.
编辑Heltonbiker写了一个有趣的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
这让我想知道,在方法
Methods may reference global names in the same way as ordinary
functions. The global scope associated with a method is the module
containing its definition. (A class is never used as a global scope.)
While one rarely encounters a good reason for using global data in a
method, there are many legitimate uses of the global scope: for one
thing, functions and modules imported into the global scope can be
used by methods, as well as functions and classes defined in it.
Usually, the class containing the method is itself defined in this
global scope (...)http://docs.python.org/2/tutorial/classes.html#method-objects
当解释器必须执行
当解释器必须执行
在python中,它似乎与模块与类范围处理有关:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
什么属性名附加到对象(及其类,以及该类的祖先)在编译时是不可决定的。因此,要么显式地进行属性查找,要么:
- 消除局部变量(在方法中)并始终使用实例变量。这不好,因为它本质上删除了具有所有优点的局部变量(至少在方法中)。
- 决定基本
x 是在运行时引用属性还是本地属性(如果没有self.x 则使用一些额外的规则来决定x = ... 何时添加新属性)。这会降低代码的可读性,因为您永远不知道名称应该是哪个,而且基本上会将所有方法中的每个局部变量都转换为公共接口的一部分(附加该名称的属性会更改方法的行为)。
两者都有额外的缺点,即它们需要特殊的方法套管。现在,"方法"只是一个通过类属性访问的常规函数。这对于各种各样的用例非常有用。