LINUX.ORG.RU

python call stack

 


0

5

В общем читал я про магические методы в python и меня заинтересовал один метод: __trunc__ — который просто отсекает дробную часть, насколько я понял. Мой вопрос состоит в том, как можно отслеживать что же всё же будет вызвано при выполнении функции. Конкретно — правда ли что int() просто вызывает метод __trunc__?

Так же интересно, зачем этот метод выделили в math:

In [1]: x = 2.5

In [2]: x.__trunc__()
Out[2]: 2
если он по сути доступен всегда?

Вот тут есть статья с подробным описанием существующих магических методов: http://www.rafekettler.com/magicmethods.html.

Метод __trunc__ там встречается как унарный математический оператор и как метод приведения, но как именно он используется для приведения я не нашёл. Как унарный оператор он вызывается функцией math.trunc, аналогично math.ceil вызывает __ceil__ и math.floor вызывает __floor__.

Мой вопрос состоит в том, как можно отслеживать что же всё же будет вызвано при выполнении функции

Я использовал для этого модуль trace, но он не залезает в магические методы:

>>> import trace
>>> t = trace.Trace(trace=True, count=False)
>>> from random import randint
>>> t.runfunc(randint, 2, 5)
 --- modulename: random, funcname: randint
random.py(218):         return self.randrange(a, b+1)
 --- modulename: random, funcname: randrange
random.py(180):         istart = _int(start)
random.py(181):         if istart != start:
random.py(183):         if stop is None:
random.py(189):         istop = _int(stop)
random.py(190):         if istop != stop:
random.py(192):         width = istop - istart
random.py(193):         if step == 1 and width > 0:
random.py(194):             return istart + self._randbelow(width)
 --- modulename: random, funcname: _randbelow
random.py(224):         random = self.random
random.py(225):         getrandbits = self.getrandbits
random.py(228):         if type(random) is BuiltinMethod or type(getrandbits) is Method:
random.py(229):             k = n.bit_length()  # don't use (n-1) here because n can be 1
random.py(230):             r = getrandbits(k)          # 0 <= r < 2**k
random.py(231):             while r >= n:
random.py(233):             return r
4

Кроме того есть ещё модуль traceback. Возможно при желании получится что-то накостылсять через sys.settrace (и заодно можно глянуть проектик http://pycallgraph.slowchop.com/en/master/).

Конкретно — правда ли что int() просто вызывает метод __trunc__

Нет, int() вызывает метод __int__

>>> '__int__' in dir(float)
True
>>> class E:
...     def __int__(self):
...             return 42
... 
>>> o = E()
>>> int(o)
42
grazor ★★
()
Ответ на: комментарий от grazor

Так же интересно, зачем этот метод выделили в math если он по сути доступен всегда?

Он доступен только для математических типов и используется математическими функциями.

>>> from pprint import pprint
>>> pprint({c.__name__: ('__trunc__' in dir(c)) for c in [int, float, complex, str, bytes, list, tuple, dict]})
{'bytes': False,
 'complex': False,
 'dict': False,
 'float': True,
 'int': True,
 'list': False,
 'str': False,
 'tuple': False}

grazor ★★
()
Ответ на: комментарий от grazor

Именно эту статью я и читал. Пример с классом показателен, как-то сразу не подумал переопределить метод. Спасибо.

conformist ★★★
() автор топика

в дополнение к предидущим ответам,

Так же интересно, зачем этот метод выделили в math

это удобно при функциональном программировании когда тебе надо передать `__trunk__` как higher-order function, например в `map()`.

val-amart ★★★★★
()
Ответ на: комментарий от val-amart

предидущим

Кхм.

это удобно при функциональном программировании когда тебе надо передать `__trunk__` как higher-order function, например в `map()`.

obj.__trunk__ прекрасно передается куда угодно. Выглядит, конечно ugly, но ведь math.trunk, если задуматься, тоже дергает этот метод; просто мы заворачивает гогно в красивую обертку.

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

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

сорри, русский не родной. а насчет абстракции это все конечно верно

val-amart ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.