对于Python 3.7
我有一个带有class属性(类范围变量)的类:
class foo:
var="value goes here"
,以及在类的 init 方法中创建的实例变量:
def __init__(self, var=var):
self.var=var
class变量与 init 的参数具有相同的名称,并且不会混淆解释器,因为解释器会将“ =”符号左侧的任何字段视为新字段方法范围内的变量。它通过为方法的范围填充一个新的名称空间(变量字典)来实现此目的,该名称空间以数组的形式实现:例如parameters[1] = "var"
或关联数组:parameters['var'] = pointer_to_value
。然后,解释器查看方法主体内部,并将通用引用替换为出现在“ =”符号的 right 侧的对“ var”的任何引用。实际上,这是一个谎言,但要比真正的理解更容易理解:
解释器标识匹配的正则表达式
.*= *var(,{0,1}| *) *(;{0,1}|\n*)
,然后将相应的pointer_to_value传递给程序的调用堆栈)。因此,解释器不必理会参数的名称,并且可以忽略var = var的歧义。歧义可以解决的事实是语言结构的副作用,而不是有意的设计决定。毕竟,问自己,在定义方法时,为什么要从要定义的方法的 inside 中访问变量?为什么要从方法定义中调用对父作用域中的变量的赋值操作?这些都是不合逻辑的动作,它们的命名空间可能性是互斥的,因此解释器无需解决歧义。
相反,解释器将“ =”符号的右侧视为现有值,并在类的名称空间中搜索变量定义。
在该方法中,实例变量也具有与类变量和参数相同的名称,并且在 init 方法中有效,因为实例变量是通过{{1}访问的}参考,例如
self
我需要从另一个方法的方法定义中访问实例变量,并且我想对该函数的参数使用相同的名称:
self.varname = varname
表达式def lookup(self, var=var):
print(var)
是否将获得class属性或instance属性? var = var
对自我有什么作用? methodname(self)
是对实际对象的引用,还是仅将解释器的行为从静态方法更改为实例方法?解释器是否自动将“ =”符号的右侧上下文作为输入到self
中的任何对象的实例属性?
在方法主体内,如果我对methodname(object)
进行了分配...
var
我已经阅读了文档和一些OOP教程以及一本新书,但这对我来说仍然不清楚。
答案 0 :(得分:3)
访问实例变量的唯一方法是将其作为self
的属性。
当您仅引用var
时,它永远不是实例变量;它始终是局部变量,封闭变量,全局变量或内置变量。
在您的方法定义中:
def lookup(self, var=var):
print(var)
…您有一个名为var
的参数。参数是局部变量。正文中的print(var)
打印该局部变量。
那呢?
def lookup(self, var=var):
var = var
同样,var
是局部变量-一个参数。因此,您只是将本地变量的当前值分配给同一变量。这没有任何作用,但是当然是完全合法的。
参数值从何而来?在函数调用时,如果传递参数,则该参数将绑定到参数;如果不这样做,它将使用默认值填充。
好,那么默认值从哪里来?
在函数定义时(执行def
语句时),在当前作用域(即var
定义的主体)及其值中查找class
会默认存储在函数对象中(应该显示为foo.lookup.__defaults__[0]
)。
因此,默认值为"value goes here"
。
请注意,不是不是闭包捕获或对class属性的其他引用。执行class
语句时,它使用相同的class
主体名称空间来构建类的属性,因此您最终以foo.var
作为{{1 }}。但是,它们是该值的完全独立的名称。您可以重新分配foo.lookup.__defaults__[0]
,并且foo.var = 3
参数的默认值仍为lookup
。
因此,要回答您的特定问题:
它将存储在类变量,实例变量或具有相同名称的新变量中吗?
以上都不是。它将它存储在一个已经存在的局部变量中,因为它是一个参数。
它将获得类变量,实例变量或方法的变量吗?
如果用“方法的变量”来表示参数,则它是最后一个。
如何明确引用这些变量?
与您明确引用其他内容的方式相同:
"value goes here"
是一个局部包含全局或内置变量。var
是实例属性,如果没有实例属性,则是类属性。self.var
是类属性,即使有实例属性也是如此。答案 1 :(得分:1)
隐式方法参数self
是 instance 。因此,尽管self.var
是实例变量,但您需要在class对象前添加前缀以访问该类变量。有时,您可能不知道类对象,然后只需使用__class__
属性,即类变量为self.__class__.var
。
回答您的三个问题
1.您在lookup
方法中进行的分配将创建一个具有相同名称var
的新变量。
2.它将获得传递给该方法的参数(我想这就是“方法变量”的意思)
3.下面的代码显示了如何显式访问这些变量(在__init__
中进行了说明,但是实际上使用哪种方法并不重要。
class A(object):
var = 'class_variable'
def __init__(self, var=var):
print('Argument var={}'.format(var))
var = var
self.var = var
print('Instance var={}'.format(self.var))
print('Class var={}'.format(self.__class__.var))
print('Alternative access to Class var={}'.format(A.var))
这给
>>> a = A()
Argument var=class_variable
Instance var=class_variable
Class var=class_variable
Alternative access to Class var=class_variable
>>> b = A('v')
Argument var=v
Instance var=v
Class var=class_variable
Alternative access to Class var=class_variable
>>> c = A()
Argument var=class_variable
Instance var=class_variable
Class var=class_variable
Alternative access to Class var=class_variable
答案 2 :(得分:1)
我将尽力回答您的问题,但如果我可以先将您的问题隔离开,
我要对该函数的参数使用相同的名称
不要这样做。这样做没有逻辑上的原因,如果让您感到困惑,现在您可以想象一下,在几个小时/天/周/月/年/年的时间内查看代码时的感受。想象一下其他人在看您代码的感觉。
对于我写的所有内容,假设我们有一个名为struct MyData
{
short Data1;
short Data2;
short Data3;
};
的实例
这将导致bob
每次实例化时都是“值在这里”。每个新对象都会将bob.var
设置为“值在此处”
var
这将导致class foo:
var="value goes here"
成为实例化期间传递给foo的任何值。如果未传递任何内容,则默认为“价值在这里”
bob.var
这将打印任何传递的内容,或者如果不传递任何内容,则显示“值在此处”
def __init__(self, var=var):
self.var=var
这无济于事,因为所讨论的def lookup(self, var=var):
print(var)
是局部作用域的,并且仅存在于方法结束之前
var
我希望这会有所帮助,只是重申一下:为不同的变量使用不同的变量名。