我是编程新手并开始学习python。可能看起来很愚蠢的问题,所以请原谅我的无知。 请考虑以下代码片段:
class Test1:
bar = 10
def display(self,foo):
self.foo=foo
print "foo : ",self.foo #80
def display1(self):
print "bar: ", self.bar #10
print "again foo: ", self.foo #80
if __name__ == '__main__':
test1 = Test1()
test1.display(80)
test1.display1()
print test1.bar #10
print test1.foo #80
我想了解使用foo和bar(wrt到我们定义它们的地方)之间的区别,因为在范围方面它们在所有地方都可以相互比较,只有区别在于一个是在函数内部和另一个是在Class内部,但它们都仍然是"实例"变量。 那么哪种做法很好?
另外,如果我稍微修改显示功能如下:
def display(self,foo):
self.foo=foo
foo = foo
print "self.foo : ",self.foo
print "foo : ",foo
有人可以解释一下python是如何看到这一点的,因为这个self
关键字在两个foo
之间带来了什么区别/重要性。
答案 0 :(得分:4)
bar
是一个类属性,foo
是一个实例属性。主要区别在于bar
将可用于所有类实例,而foo
仅在您在该实例上调用display时才可用于实例
>>> ins1 = Test1()
ins1.bar
工作正常,因为它是一个类属性,并且由所有实例共享。
>>> ins1.bar
10
但你不能直接在这里访问foo,因为它尚未定义:
>>> ins1.foo
Traceback (most recent call last):
File "<ipython-input-62-9495b4da308f>", line 1, in <module>
ins1.foo
AttributeError: Test1 instance has no attribute 'foo'
>>> ins1.display(12)
foo : 12
>>> ins1.foo
12
如果要在创建实例时初始化某些实例属性,请将它们放在__init__
方法中。
class A(object):
bar = 10
def __init__(self, foo):
self.foo = foo #this gets initialized when the instance is created
def func(self, x):
self.spam = x #this will be available only when you call func() on the instance
...
>>> a = A(10)
>>> a.bar
10
>>> a.foo
10
>>> a.spam
Traceback (most recent call last):
File "<ipython-input-85-3b4ed07da1b4>", line 1, in <module>
a.spam
AttributeError: 'A' object has no attribute 'spam'
>>> a.func(2)
>>> a.spam
2
答案 1 :(得分:3)
bar
是一个类属性。由于Python中的类是对象,因此它们也可以具有属性。 bar
只是碰巧住在Test
对象上,而不是它的实例。
由于Python解析属性查找的方式,看起来test1
具有bar
属性,但它没有。
foo
在调用test1
后依赖实例display(80)
。这意味着Test
的不同实例可以在各自的foo
属性中具有不同的值。
当然,您可以将类变量用作某种“共享默认值”,然后可以使用实例属性“覆盖”,但这可能会让人感到困惑。
第二个问题
def display(self,foo):
self.foo=foo
foo = foo
print "self.foo : ",self.foo
print "foo : ",foo
让我们只是弄清楚一个细节:self
不是关键字,只是召唤第一个参数“self”,你也可以称之为“this”或“that”或“bar” “如果你喜欢,但我不建议这样做。
Python将传递对象,在该对象上调用该方法作为第一个参数。
def display(self,foo):
这个foo是显示实例函数的第一个参数的名称。
self.foo=foo
这将使用实例的名称“foo”设置属性,在该属性上调用display()
作为第一个参数传递的值。使用您的示例test1.display(80)
,self
将为test1
,foo
为80
,test1.foo
将设置为80
。
foo = foo
这一点都没有。它引用了第一个参数foo
。
接下来的两行再次引用实例变量foo
和第一个参数foo
。
答案 2 :(得分:1)
就我个人而言,我不喜欢在__init__
以外的方法中定义实例变量,或者在上面的示例中定义像bar
这样的类变量。
再一次,就个人而言,我希望通过查看顶部来看到我班上的每个成员。无论是用作实例变量的类变量(我通常不做的事情)还是在__init__
中定义的实例变量,都可以很容易地告诉我们在类中定义了什么和没有定义检查类定义的第一部分。
如果您不需要作为类成员访问变量(即,您只是在那里定义它以避免在self.variable = val
方法中编写__init__
,那么我会避开它如果你可能需要将它作为一个类变量来访问,那么在我的书中就可以使用bar
来做你想做的事了。
这将是我写作课程的首选方式。
class Test1:
def __init__(self):
self.foo = None
self.bar = 10
def display(self,foo):
self.foo=foo
print "foo : ",self.foo #80
def display1(self):
print "bar: ", self.bar #10
print "again foo: ", self.foo #80