2016-12-08 8 views
0

Я хочу создать функцию, которая будет вызываться всякий раз, когда вызывающий объект получает аргументы неправильного экземпляра, который будет печатать атрибут вызывающего абонента __doc__ и выйти. Функция заключается в следующем:Разрешить функцию вызова для получения атрибута вызывающего абонента в Python

def checktype(objects,instances): 
    if not all([isinstance(obj,instance) for 
       obj,instance in zip(objects,instances)]): 
     print 'Type Error' 
     #Get __doc__ from caller 
     print __doc__ 
     exit() 

я застрял на стадии, где я должен получить атрибут __doc__. Я знаю, что inspect модуль может сделать это, в некотором смысле, как следующее:

name=inspect.stack()[1][3] 
possibles=globals().copy() 
__doc__= possibles.get(name).__doc__ 

(вы можете предложить еще один, который совместим с любой версией Python, включая 3.5)

, но я думаю, что должно быть другой путь. Причина моего скептицизма заключается в том, что встроенный оператор return возвращает что-то вызывающему абоненту, поэтому это означает, что должна быть «крючок» или «труба», доступная дочерней функции, которая используется как средний для обмена информацией с родителем. Так что начальный вопрос, который вызвал мой интерес, был:

Этот труба отправляется только по почте и никакая информация не может быть отправлена ​​назад?

Я не смог ответить на это, поскольку заявление return вкратце объяснено на сайтах, которые я искал. Кроме того, модуль inspect, насколько я могу судить, сохраняет несколько кадров в стеке и постоянно работает в фоновом режиме. Для меня это похоже на то, что я пытаюсь убить муху с помощью мини-пушки. Мне просто нужно имя функции вызывающего абонента, а не функция 10 кадров раньше. Если этого не сделать, это, на мой взгляд, функция, которую должен иметь Python. Мой вопрос:

Каким будет pythonic-программный способ получить атрибуты вызывающего абонента в Python с универсальной поддержкой? Извините меня, если в моем вопросе есть незнание, я открыт для любых исправлений и «разумов». Спасибо всем за ваши ответы.

+1

Я думаю, что декоратор бы целесообразно для этого. – polku

+0

@polku Мне было бы интересно узнать, как передать аргументы функции внутри декоратора. Обертка - хорошая идея, если у меня есть набор обработчиков сигналов, но я думаю, что это может быть подходящим только для дистрибутива Linux. –

+0

IDK, как вы знакомы с декораторами, но вы не передаете ему аргументы функции. Я понимаю, что вы хотите, чтобы механизм проверки типов повторно использовался для разных функций, вот что я использовал бы (это и настраиваемое исключение вместо печати и выхода), но, возможно, я ошибаюсь. – polku

ответ

0

У меня есть несколько функций, которые могут быть связаны с вашим вопросом

import sys 

def position(level = 0): 
    """return a tuple (code, lasti, lineno) where this function is called 

    If level > 0, go back up to that level in the calling stack. 
    """ 
    frame = sys._getframe(level + 1) 
    try: 
     return (frame.f_code, frame.f_lasti, frame.f_lineno) 
    finally: 
     del frame 

def line(level = 0): 
    """return a tuple (lineno, filename, funcname) where this function is called 

    If level > 0, go back up to that level in the calling stack. 

    The filename is the name in python's co_filename member 
    of code objects. 
    """ 
    code, lasti, lineno = position(level=level+1) 
    return (lineno, code.co_filename, code.co_name) 

def _globals(level = 0): 
    """return the globals() where this function is called 

    If level > 0, go back up to that level in the calling stack. 

    """ 
    frame = sys._getframe(level + 1) 
    try: 
     return frame.f_globals 
    finally: 
     del frame 
+0

Благодарим вас за ответ. Насколько я могу судить, вы предлагаете использовать 'sys._getframe (1) .f_code.co_name'. Это дает мне имя функции, но я не могу получить какой-либо другой атрибут. Это хорошая идея. Совместима ли эта Windows? –

+0

попробуйте '_globals (1) [line (1) [2]] .__ doc__'. Все это агностик. – Gribouillis

+0

Хорошо, это делает то, что было запрошено и очень аккуратно, поскольку я использую встроенный модуль: 'f = sys._getframe (1); print f.f_globals [f.f_code.co_name] .__ doc__' –