5

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

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

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

有人可以解释一下python是如何看待这个的,就像这个self关键字在两个foo.

4

3 回答 3

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
于 2013-07-09T18:08:52.367 回答
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将因此设置为。foo80test1.foo80

    foo = foo

这根本没有任何作用。它引用了第一个参数foo

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

于 2013-07-09T18:28:22.523 回答
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
于 2013-07-09T18:10:00.113 回答