使用self访问类方法和变量

9
在下面的示例中,Test类有两个实例方法和一个类方法。
在set_cls_var_1方法中,我使用self设置了类变量。
在set_cls_var_2方法中,我使用self调用了类方法。
   class Test():

        #class variable
        cls_var = 10

        def __init__(self):
           obj_var=20

        def set_cls_var_1(self,val):
            #second method to access class variable
            print "first "
            self.cls_var = val

        def set_cls_var_2(self):
            print "second"
            self.task(200)

        @classmethod
        def task(cls,val):
            cls.cls_var = val


t=Test()

#set class variable by first method
t.set_cls_var_1(100)

print Test.cls_var

#set class variable by second method
t.set_cls_var_2()

print Test.cls_var

输出

first 
10
second
200

预期输出

first 
100
second
200

我的问题是:为什么只有classmethod可以由self调用,而类变量不行?

在实例上分配属性永远不会分配到类属性。 - user2357112
1
但是当我可以在“set_cls_var_1”中访问“cls_var”,例如“print self.cls_var”时,为什么和如何可能,我不理解。 - Kallz
这意味着我只能在实例方法中获取类变量,不能使用self在实例方法中设置类变量。 - Kallz
3个回答

11
当您尝试使用self访问对象的属性时,Python首先搜索对象的属性。如果它在那里找不到,那么它就会搜索对象的类的属性。这就是你的情况;
Python首先搜索t的属性。它没有找到cls_var,所以它然后搜索T类的属性。它找到了cls_var,所以停止搜索并返回cls_var的值。
然而,当将属性分配给self时,Python总是直接将它们分配给对象,而不是对象的类,除非明确告诉它这样做。这就是为什么将self.cls_var赋值为100没有影响Testcls_var属性的原因。

为什么在类方法中尝试打印cls.obj_var时会出错,如果Python首先搜索对象的属性。如果它在那里找不到它,那么它会搜索对象的类属性。 - Kallz
@Kallz 因为 obj_var 属于 对象 而不是 __。Python 报错是因为 T 没有 obj_var,只有 T 的对象才有。 - Christian Dean

8

我发现有人总是用以下方式在实例方法中访问classmethod或变量

class Test():
    #class variable
    cls_var = 10

    def __init__(self):
        obj_var=20

    def set_cls_var_1(self,val):
        #first method to access class variable
        print "first type"
        cls = self.__class__
        cls.cls_var = val



t=Test()
#set class variable by first method

t.set_cls_var_1(100)

print Test.cls_var

2
当你定义类Test时,Python会创建一个名为Test的类对象,该对象具有一个属性cls_var,其值为10。当你实例化这个类时,创建的对象没有cls_var属性。在调用self.cls_var时,实际上是检索到类属性,因为Python解析属性的方式如此。
然而,当设置self.cls_var时,该值被设置在对象级别!因此,对self.cls_var的进一步调用将给出对象属性的值,而不再是类的属性!
也许这段代码能更清楚地说明问题:
class A(object):
    a = 1
a = A()
print a.a  # prints 1
A.a = 2
print a.a  # prints 2

即使在类级别设置值,修改会反映在对象上,因为当在对象级别找不到属性时,Python会在类中查找该属性。

调用 Test.cls_var 时,访问的是类的 cls_var 属性!而不是刚刚修改的对象的属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接