суббота, 2 ноября 2019 г.

ЛМНты Python, 26 - 30

>>> Zen of Python

Модуль this хранит принципы программирования на Python, извеcтные как Zen of Python:

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

>>> О модуле

Больше узнать об импортированном модуле позволяет функция dir(), выводящая имена из глобального пространства имен модуля. Например, для ранее импортированного модуля this:

>>> dir(this)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'c', 'd', 'i', 's']

Атрибут __file__ содержит путь к файлу модуля:

>>> this.__file__
'C:\\Python\\Python36\\lib\\this.py'

Если импортирован пакет, то __file__ указывает на файл __init__.py этого пакета:

>>> import lxml
>>> lxml.__file__
'C:\\Python\\Python36\\lib\\site-packages\\lxml\\__init__.py'

У встроенных модулей Python атрибут __file__ отсутствует:

>>> import math
>>> math.__file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'math' has no attribute '__file__'

>>> __contains__

Операторы in и not in вызывают метод __contains__ объекта, чтобы проверить, содержит ли объект значение слева от оператора. Для словаря in проверяет вхождение значения в список ключей:

>>> d = {'a':'эй', 'b':'би'}
>>> 'a' in d
True
>>> 'эй' in d
False

Можно изменить это поведение, переопределив метод __contains__ в классе, унаследованном от словаря:

>>> class MyDict(dict):
...     def __contains__(self, val):
...         if val in self.values():
...             return True
...         else:
...             return False
...
>>> d1 = MyDict(d)
>>> 'a' in d1
False
>>> 'эй' in d1
True

>>> str и repr

Методы __str__ и __repr__ отличаются тем, что первый возвращает строковое представление объекта, а второй – строку, при выполнении которой создается такой же объект. Эти методы неявно вызываются встроенными функциями str и repr, соответственно. Например,

>>> s = 'привет'
>>> repr(s)
"'привет'"
>>> str(s)
'привет'

Функция repr вернула выражение Python, которое можно исполнить с помощью функции eval:

>>> s1 = eval(repr(s))
>>> s1
'привет'
>>> type(s1)
<class 'str'>

Функция str вернула строку, которую нельзя исполнить:

>>> s2 = eval(str(s))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'привет' is not defined

>>> repr может

Если для класса определить метод __repr__ и не определять __str__, то первый будет работать за двоих. Хотя это не очевидно, если вы не голландец :)

>>> class Cell(object):
...     def __init__(self, val):
...         self.val = val
...     def __repr__(self):
...         return 'Cell(%s)' % self.val
...
>>> c = Cell(3.14)
>>> str(c)
'Cell(3.14)'
>>> repr(c)
'Cell(3.14)'

Выражение, возвращаемое методом __repr__ вашего класса, априори считается более информативным, чем то, что возвращают методы __repr__ и __str__, унаследованные от object:

>>> class Cell(object):
...     def __init__(self, val):
...         self.val = val
...
>>> c = Cell(3.14)
>>> str(c)
'<__main__.Cell object at 0x0000026EF9F90D68>'
>>> repr(c)
'<__main__.Cell object at 0x0000026EF9F90D68>'

Комментариев нет:

Отправить комментарий