Логи c в конструкторе Python - PullRequest
1 голос
/ 27 марта 2020

Я новичок в OOP в Python, и давайте предположим, что у меня есть класс, который выполняет простые вычисления:

class Calc: 
    def __init__(self, n1, n2): 
        self.n1 = n1 
        self.n2 = n2 

    def sum(self):
        return self.n1 + self.n2

В этом упрощенном примере, каков наилучший способ проверки атрибуты класса? Например, скажите, если я ожидаю float для n1 и n2, чтобы я определял свой конструктор как:

self.n1 = float(n1) 
self.n2 = float(n2) 

Если бы n1 или n2 было None, я бы получить ошибку атрибута, так как NoneType не может быть float - по некоторым причинам, это неправильно, потому что мы имеем logi c в конструкторе класса Calc, чтобы поймать это.

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

Могу ли я использовать какую-то технику для проверки на лету, например, декораторы или аннотации свойств?

Любой совет приветствуется

Ответы [ 3 ]

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

Это зависит от того, откуда вы берете свои данные и насколько просто вы хотите, чтобы ваш код был. Если вы хотите, чтобы этот класс полностью проверял входные данные, которым вы не можете доверять, например, потому что они поступают непосредственно из пользовательского ввода, тогда вы делаете явную проверку:

class Calc: 
    def __init__(self, n1, n2): 
        if not all(isinstance(n, float) for n in (n1, n2)):
            raise TypeError('All arguments are required to be floats')

        self.n1 = n1 
        self.n2 = n2 

Следующий уровень ниже этого будет отладочные утверждения :

class Calc: 
    def __init__(self, n1, n2): 
        assert all(isinstance(n, float) for n in (n1, n2)), 'Float arguments required'

        self.n1 = n1 
        self.n2 = n2 

assert операторы могут быть отключены для повышения производительности , поэтому не следует полагаться на фактическую проверку. Однако, если ваши данные проходят через уровень проверки до этого, и вы обычно ожидаете, что ваши аргументы будут плавающими, то это хорошо и кратко. Это также удваивается как довольно приличное самодокументирование.

Следующим шагом после этого являются аннотации типа :

class Calc: 
    def __init__(self, n1: float, n2: float): 
        self.n1 = n1 
        self.n2 = n2 

Это еще более читабельно и самодокументируется, но никогда ничего не делает во время выполнения. Это зависит от stati c type checkers для анализа вашего кода и выявления очевидных ошибок, таких как:

Calc(input(), input())

Такие проблемы могут быть обнаружены и указаны вам stati c проверка типов (поскольку известно, что input возвращает строки, которые не соответствуют подсказке типа), и они интегрированы в большинство современных сред IDE.

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

1 голос
/ 27 марта 2020

Проверка типов - это бой, который вы не можете выиграть. Это сопряжено с серьезными издержками и по-прежнему не защитит вас от ошибок - если вы получаете неправильные типы, все, что вы можете сделать, - это потерпеть неудачу.

По умолчанию статические типы проверяются с помощью подсказок типов :

class Calc: 
    def __init__(self, n1: float, n2: float): 
        self.n1 = n1 
        self.n2 = n2 

    def sum(self):
        return self.n1 + self.n2

Это позволяет IDE и средствам проверки типов, например, mypy, статически проверять правильность типа. Он не имеет затрат времени выполнения и может быть проверен как часть непрерывной интеграции и т. П.

Для критических частей, где поврежденное состояние недопустимо, используйте утверждения для проверки типов.

class Calc: 
    def __init__(self, n1: float, n2: float):
        assert isinstance(n1, float)
        assert isinstance(n2, float)
        self.n1 = n1 
        self.n2 = n2 

    def sum(self):
        return self.n1 + self.n2

Утверждения имеют накладные расходы времени выполнения, но их можно полностью отключить после проверки правильности (типа).

0 голосов
/ 27 марта 2020

Просто проверьте значения перед началом

class Calc: 
    def validate(self,n1,n2):
        if not isinstance(n1, float) or not isinstance(n2, float):
            return False
        return True

    def __init__(self, n1, n2): 
        if self.validate(n1,n2):
            self.n1 = n1 
            self.n2 = n2 

    def sum(self):
        return self.n1 + self.n2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...