Доступ к методу класса и переменной с помощью self

В приведенном ниже примере класс 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 может вызывать себя, почему не переменная класса


person Kallz    schedule 15.07.2017    source источник
comment
Присвоение атрибутов экземпляру никогда не будет присвоено атрибуту класса.   -  person user2357112 supports Monica    schedule 15.07.2017
comment
Но когда я могу получить доступ к cls_var в set_cls_var_1, например, print self.cls_var. почему и как это возможно, я не понимаю   -  person Kallz    schedule 15.07.2017
comment
это означает, что я могу получить переменную класса только в методе экземпляра, не могу установить переменную класса в методе экземпляра, используя себя   -  person Kallz    schedule 15.07.2017


Ответы (3)


Когда вы пытаетесь получить доступ к атрибуту объекта с помощью self, Python сначала ищет атрибуты объекта. Если он не может найти его там, то ищет атрибуты класса объекта. Это то, что происходит в вашем случае;

Python сначала ищет атрибуты t. Он не находит cls_var, поэтому ищет атрибуты класса T. Он находит cls_var, поэтому останавливается и возвращает значение cls_var.

Однако при назначении атрибутов self Python всегда присваивает их непосредственно объекту, а не классу объекта, если это явно не указано. Вот почему назначение self.cls_var на 100 не повлияло на атрибут cls_var Test.

person Christian Dean    schedule 15.07.2017
comment
тогда почему ошибка при попытке напечатать cls.obj_var в методе класса, если Python сначала ищет атрибуты объекта. Если он не может найти его там, он ищет атрибуты класса объекта. - person Kallz; 15.07.2017
comment
@Kallz Потому что obj_var принадлежит объекту, а не классу. Python вызвал ошибку, потому что T не имеет obj_var, а есть только у объекта T. - person Christian Dean; 15.07.2017

Я нахожу что-то еще, что всегда использует следующий способ доступа к методу класса или переменной в методе экземпляра

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
person Kallz    schedule 15.07.2017

При определении класса 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 класса, к которому вы обращаетесь! Не тот объект, который вы только что изменили.

person Anis    schedule 15.07.2017