переопределение существующей функции как метода класса - PullRequest
0 голосов
/ 28 апреля 2020

Я учусь пользоваться классами. Я хочу создать класс с несколькими методами и атрибутами. В моем случае некоторые методы могут быть функциями, которые я написал в другом месте кода.

Хорошая ли практика - переопределять функции как методы класса, как в следующем примере?

def f(x,b):
    return b*x

class Class1:
    def __init__(self,b):
        self.b=8.
    def f(self,x):
        return f(x,self.b) 


instance1=Class1(5)
print instance1.f(7.)

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

Как правильно определить методы с использованием функции, написанной в другом месте?

1 Ответ

2 голосов
/ 28 апреля 2020

Функции ...

Рассмотрим следующую группу функций:

def stack_push(stack, value):
    stack.append(value)

def stack_is_empty(stack):
    return len(stack) == 0

def stack_pop(stack):
    return stack.pop()

Вместе они реализуют стек в виде встроенного списка. Пока вы не взаимодействуете со списком напрямую, они разрешают использовать только only , добавляя значения к одному концу, удаляя значения с того же конца и проверяя, пустой ли стек:

>>> s = []
>>> stack_push(s, 3)
>>> stack_push(s, 5)
>>> stack_push(s, 10)
>>> if not stack_is_empty(s): stack_pop(s)
10
>>> if not stack_is_empty(s): stack_pop(s)
5
>>> if not stack_is_empty(s): stack_pop(s)
3
>>> if not stack_is_empty(s): stack_pop(s)
>>>

... против методов

Обратите внимание, что каждая функция принимает один и тот же аргумент: список обрабатывается как стек. Это указывает на то, что вместо этого мы можем написать class the, представляющий стек, так что нам не нужно поддерживать list, который потенциально может (неправильно) использоваться вне этих трех функций. Это также гарантирует, что мы начнем с пустого списка для нашего нового стека.

class Stack:
    def __init__(self):
        self.data = []

    def push(self, value):
        self.data.append(value)

    def is_empty(self):
        return len(self.data) == 0

    def pop(self):
        return self.data.pop()

Теперь мы не работаем с list, который поддерживает все виды операций, не связанных со стеком, таких как индексация, итерация, и мутация в начале или в середине списка: мы можем только pu sh, щелкнуть и проверить пустоту.

>>> s = Stack()

Такие вещи, как s[3], s.insert(2, 9) , et c не допускаются.

(Обратите внимание, что нам строго не запрещается использовать s.data напрямую, но это считается плохой практикой, если только класс не скажет, что это нормально в документация. В этом случае мы не допускаем это.)

Мы используем эти методы так же, как мы использовали функции stack_*.

>>> s.push(3)
>>> s.push(5)
>>> s.push(10)
>>> if not s.is_empty(): s.pop()
10
>>> if not s.is_empty(): s.pop()
5
>>> if not s.is_empty(): s.pop()
3
>>> if not s.is_empty(): s.pop()
>>>

Разница в том, что мы не можем «случайно» использовать другие методы списка, потому что Stack не предоставляет их.

>>> s.insert(3, 9)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Stack' object has no attribute 'insert'

Наконец, обратите внимание, что мы не пишем наши оригинальные функции stack_* и используйте их в определении класса Stack: в этом нет необходимости; мы просто определяем методы явно внутри оператора class.

# No.
class Stack:
    def push(self, value):
        stack_push(self.data, value)

Мы также не продолжаем использовать функции stack_* в экземпляре Stack.

#  No no no!
>>> stack_is_empty(s.data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...