Возвращая класс себе в python - PullRequest
1 голос
/ 11 марта 2020

Очень простой вопрос, но я новичок в python как объектно-ориентированный язык программирования. Я пытаюсь написать класс. Представьте, что он организован следующим образом:

class myClass:
    def __init__(self,a,b,runit=True):
        self.a = a
        self.b = b
        if runit:
            self.run_func()

    def run_func(self):
        self.c = self.a*self.b
        return

Итак, как вы видите, класс инициализируется только с a и b. По умолчанию он инициализирует c из этих аргументов, но это не обязательно. Теперь позвольте мне проиллюстрировать три варианта использования, которые, по моему мнению, должны вести себя одинаково, но не являются такими:

# Use 1
test = myClass(5,2)
print(test.c)

# Use 2
test = myClass(5,2,runit=False)
test.run_func()
print(test.c)

# Use 3
test = myClass(5,2,runit=False).run_func()
print(test.c)

Это возвращает следующее:

10
10
Traceback (most recent call last):

  File "<ipython-input-37-cb854baa3a0c>", line 23, in <module>
    print(test.c)

AttributeError: 'NoneType' object has no attribute 'c'

Почему экземпляр класса не может работать немедленно и передать этот результат в test за один шаг? В моей голове (1) и (2) - это один и тот же набор операций, за исключением того, что одна разбита на два шага, а другая выполняется в одной строке.

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

Ответы [ 5 ]

2 голосов
/ 11 марта 2020

В случае, если 3

 test = myClass(5,2,runit=False).run_func()
 print(test.c)

test - это не объект, а возврат run_fun c (), который равен нулю и действительно не имеет атрибута c

2 голосов
/ 11 марта 2020

Давайте посмотрим на вызов метода:

test = myClass(5,2,runit=False).run_func()

Давайте разберемся с этим. Сначала вы создаете экземпляр myClass, а затем вызываете run_func для этого экземпляра. Это возвращаемое значение run_func, которое вы назначаете для теста, и поскольку run_func ничего не возвращает test равно None, что приводит к вашей ошибке.

В качестве другого способа увидеть это, попробуйте следующее:

class myClass:
    def __init__(self,a,b,runit=True):
        self.a = a
        self.b = b
        if runit:
            self.run_func()

    def run_func(self):
        self.c = self.a*self.b
        return 11

test = myClass(5,2,runit=False).run_func()
print(test) # will print 11
2 голосов
/ 11 марта 2020

В третьем случае test присваивается возвращаемое значение run_func(). Он имеет return, который возвращает None, поэтому test = None.

2 голосов
/ 11 марта 2020

при # Use 3 myClass(5,2,runit=False).run_func() возвращает None

, чтобы исправить, вы можете вернуть self:

def run_func(self):
        self.c = self.a*self.b
        return self

test = myClass(5,2,runit=False).run_func()
print(test.c)

вывод:

10

или Вы не должны устанавливать свой флаг runit на False и использовать:

class myClass:
    def __init__(self,a,b,runit=True):
        self.a = a
        self.b = b
        if runit:
            self.run_func()

    def run_func(self):
        self.c = self.a*self.b

test = myClass(5,2)
print(test.c)

вывод:

10
2 голосов
/ 11 марта 2020

run_func должен вернуть self:

    def run_func(self):
        self.c = self.a*self.b
        return self

с указанием return без значения, следующего за ним, аналогично записи return None. Вы получаете это исключение, потому что None не имеет атрибута с именем c.

...