理解python类属性

理解python类属性,python,python-2.7,python-3.x,Python,Python 2.7,Python 3.x,我对编程非常陌生,并开始学习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

我对编程非常陌生,并开始学习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到我们定义它们的地方)之间的区别是什么,因为在范围方面,它们在所有地方都可以平等地访问,彼此比较,唯一的区别是一个在函数内部,另一个在类内部,但它们仍然是“实例”变量。 那么哪一个是好的实践呢

另外,如果我稍微修改一下显示功能,如下所示:

    def display(self,foo):
        self.foo=foo
        foo = foo
        print "self.foo : ",self.foo 
        print "foo : ",foo 

有人能解释一下python是如何看待这一点的,因为这个
self
关键字在两个
foo
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

就个人而言,我不喜欢在方法内部定义实例变量,除了
\uuuu init\uuuu
或者在上面的示例中定义为类变量,如
bar

同样,就我个人而言,我喜欢通过看顶端来看到我班上的每个成员。无论是用作实例变量的类变量(我通常不这么做)还是在
\uuuu init\uuuu
中定义的实例变量,通过检查类定义的第一部分,可以很容易地判断类中定义了什么和没有定义什么

如果您不需要以类成员的身份访问变量(即,您在那里定义它只是为了避免在
\uuuu init\uuuu
方法中写入
self.variable=val
),那么我会避开它。如果您可能需要以类变量的身份访问它,那么在我的书中使用
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

bar
是一个类属性。由于Python中的类是对象,它们也可以有属性。
bar
恰好位于该
Test
对象上,而不是其实例

由于Python解析属性查找的方式,它看起来像是
test1
有一个
bar
属性,但它没有

另一方面,
foo
在调用
display(80)
后位于实例
test1
上。这意味着
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是display实例函数的第一个参数的名称

    self.foo=foo
这会将名为“foo”的实例属性设置为作为第一个参数传递的值,您在该实例上调用了
display()
。使用示例
test1.display(80)
self
将是
test1
foo
80
test1。foo
将因此设置为
80

    foo = foo
这根本不起作用。它引用第一个参数
foo


接下来的两行再次引用实例变量
foo
,第一个参数
foo

否,
bar
不是实例变量。这两行非常不同,这就是为什么它不是关于“良好实践”的原因。这是关于什么适合您的情况,因为它们有不同的用途。另外,
self.bar
工作是因为名称
bar
首先在实例的命名空间中搜索,然后在类中搜索。
self.bar
工作的事实并不总是意味着
bar
是一个实例变量。我认为主要区别在于类属性是“共享的”,而不是它对所有实例都可用。
    foo = foo