Class Invariants in Python

Class invariants can definitely be useful in coding, since they can give instant feedback when an obvious programming error is detected, and also improve code readability as explicit information about which arguments and return value may be. I am sure this applies to Python as well.

However, as a rule, in Python, argument testing does not seem to be a โ€œpufonicโ€ way of doing something, like against the duck idiom.

My questions:

  • What is the Pythonic way of using assertions in code?

    For example, if I had the following function:

    def do_something(name, path, client):
        assert isinstance(name, str)
        assert path.endswith('/')
        assert hasattr(client, "connect")
    
  • In general, when are there too many statements?

I would be glad to hear your opinion about this!

+4
1

:

Pythonic?

, . , . , - , :

  • hinting, IDE , .

  • .

  • try/except , .

  • , .

  • assert .

.

. Pythonic , , , PEP 484:

[ hinting] , Python , (, ) .

:

def greeting(name: str) -> str:
    return 'Hello ' + name 

typing . ...

__annotations__, . off-line, . , linter.

. , , , , .


try/except

- , . - , . , , :

 class Dog(object):
     """Canis lupus familiaris."""

     self.name = str()
     """The name you call it."""


     def __init__(self, name: str):
         """What're you gonna name him?"""

         self.name = name


     def speak(self, repeat=0):
         """Make dog bark. Can optionally be repeated."""

         print("{dog} stares at you blankly.".format(dog=self.name))

         for i in range(repeat):
             print("{dog} says: 'Woof!'".format(dog=self.name)

, , self.name. speak(). , self.name a ...

 class Dog(object):
     """Canis lupus familiaris."""

     self._name = str()
     """The name on the microchip."""

     self.name = property()
     """The name on the collar."""


     def __init__(self, name: str):
         """What're you gonna name him?"""

         if not name and not name.isalpha():
             raise ValueError("Name must exist and be pronouncable.")

         self._name = name


     def speak(self, repeat=0):
         """Make dog bark. Can optionally be repeated."""

         try:
             print("{dog} stares at you blankly".format(dog=self.name))

             if repeat < 0:
                 raise ValueError("Cannot negatively bark.")

             for i in range(repeat):
                 print("{dog} says: 'Woof!'".format(dog=self.name))

         except (ValueError, TypeError) as e:
             raise RuntimeError("Dog unable to speak.") from e


     @property
     def name(self):
         """Gets name."""

         return self._name

, self.name ; , - self._x. , try/except , , .


, ?

, 100% - "Pythonic" , . , , , assert , Python wiki:

Python - Python. , : , , - by_name, by_id.

:

from types import *
  class MyDB:
  ...
  def add(self, id, name):
    assert type(id) is IntType, "id is not an integer: %r" % id
    assert type(name) is StringType, "name is not a string: %r" % name

, "" " "; , , "".

. isinstance(), :

, :

class PrintQueueList:
  ...
  def add(self, new_queue):
   assert new_queue not in self._list, \
     "%r is already in %r" % (self, new_queue)
   assert isinstance(new_queue, PrintQueue), \
     "%r is not a print queue" % new_queue

, , : . , , , .

,
(ex: assert <statement>, "<message>") AssertionError, . , .

isinstance() : , , , . , .

:

  • ,
  • " " ( , .)
  • , ,

, , , . , , , Pythonic.

+6

Source: https://habr.com/ru/post/1660988/


All Articles