Для этого я использую следующий шаблон.
namespace stuff {
template< typename ContainerT, typename PredicateT >
void erase_if( ContainerT& items, const PredicateT& predicate ) {
for( auto it = items.begin(); it != items.end(); ) {
if( predicate(*it) ) it = items.erase(it);
else ++it;
}
};
}
Это ничего не вернет, но это удалит элементы из std :: map.
Пример использования:
// 'container' could be a std::map
// 'item_type' is what you might store in your container
using stuff::erase_if;
erase_if(container, []( item_type& item ) {
return /* insert appropriate test */;
});
Второй пример (позволяет передать тестовое значение):
// 'test_value' is value that you might inject into your predicate.
// 'property' is just used to provide a stand-in test
using stuff::erase_if;
int test_value = 4; // or use whatever appropriate type and value
erase_if(container, [&test_value]( item_type& item ) {
return item.property < test_value; // or whatever appropriate test
});
inspect.getframeinfo и другие связанные функции в проверять
могут помочь:
& gt; & gt; & gt; & gt; проверка импорта & gt; & gt; & gt; & gt; & gt; & gt; def f1 (): f2 () ... & gt; & gt; & gt; & gt; & gt; def f2 (): ... curframe = inspect.currentframe () ... calframe = inspect.getouterframes (curframe, 2) ... print 'имя вызывающего абонента:', calframe [1] [3] ... & gt; & GT; & GT; f1 () имя вызывающего абонента: f1 & gt; & gt; & gt; & gt;
эта интроспекция предназначена для помощи в отладке и разработке; нецелесообразно полагаться на это для производственных целей.
Я придумал несколько более длинную версию, которая пытается создать полное имя метода, включая модуль и класс.
https://gist.github.com/2151727 (rev 9cccbf)
# Public Domain, то есть не стесняйтесь копировать / вставлять # Считается, что взлом в Python 2 import проверяет def caller_name (skip = 2): "" "Получить имя вызывающего абонента в формате module.class.method` skip` указывает, сколько уровней стека пропустить при получении имени вызывающего абонента. skip = 1 означает «кто меня звонит», skip = 2 «кто звонит моему абоненту» и т. д. Пустая строка возвращается, если пропущенные уровни превышают высоту стека »« »stack = inspect.stack () start = 0 + skip if len ( стек) start + 1: return '' parentframe = stack [start] [0] name = [] module = inspect.getmodule (parentframe) # `modname` может быть None, когда кадр выполняется непосредственно в консоли # TODO (techtonik): рассмотрите возможность использования __main__ if module: name.append (module .__ name__) # обнаружить имя класса, если «self» в parentframe.f_locals: # Я не знаю, какой способ обнаружить вызов из метода объекта # XXX: похоже, нет способа обнаружить статический вызов метода - это будет # просто вызов функции name.append (parentframe.f_locals ['self'] .__ class __.__ name__) codename = parentframe.f_code.co_name, если codename! = '& lt; module & gt;': # верхний уровень обычно name.append (кодовое имя) # функция или метод ## Избегайте циклических ссылок и исправлений кадров # https://docs.python.org/2.7/library/inspect.html#the-interpreter-stack del parentframe, возврат в стеке " . ". join (name)
stack
, он все еще теряет фреймы из-за циклических ссылок, как описано в inspect-docs
– ankostis
10 December 2016 в 12:56
Кажется, что все работает отлично:
import sys print sys._getframe (). f_back.f_code.co_name
Я нашел способ, если вы проходите через классы и хотите, чтобы класс принадлежал методу AND. Это требует немного работы по извлечению, но это делает ее точкой. Это работает в Python 2.7.13.
import inspect, os class ClassOne: def method1 (self): classtwoObj.method2 () class ClassTwo: def method2 (self): curframe = inspect.currentframe () calframe = inspect.getouterframes (curframe, 4) print '\nI был вызван из', calframe [1] [3], \ 'in', calframe [1] [4] [0] [6: -2] # создавать объекты для доступа к классам classoneObj = ClassOne () classtwoObj = ClassTwo () # запустить программу os.system ('cls') classoneObj.method1 ()
Более короткая версия:
import проверить def f1 (): f2 () def f2 (): print 'имя вызывающего абонента:', inspect.stack () [1] [3] f1 ()
(благодаря @Alex и Stefaan Lippen )
Немного об объединении вещей выше.
def print_caller_name (stack_size = 3): def wrapper (fn): def internal (* args, ** kwargs): import проверить stack = inspect.stack ( ) modules = [(index, inspect.getmodule (stack [index] [0])) для индекса в обратном (диапазон (1, stack_size))] module_name_lengths = [len (module .__ name__) для _, модуль в модулях] s = '{index: & gt; 5}: {module: ^% i}: {name}'% (max (module_name_lengths) + 4) callers = ['', s.format (index = 'level', module = ' module ', name =' name '),' - '* 50] для индекса, модуль в модулях: callers.append (s.format (index = index, module = module .__ name__, name = stack [index] [3] )) callers.append (s.format (index = 0, module = fn .__ module__, name = fn .__ name__)) callers.append ('') print ('\n'.join (вызывающие)) fn (* args , ** kwargs) return inner return wrapper
Использование:
@print_caller_name (4) def foo (): return 'foobar' def bar () : return foo () def baz (): return bar () def fizz (): return baz () fizz ()
output is
level : module: name -------- ------------------------------------------ 3: Нет: fizz 2: None : baz 1: None: bar 0: __main__: foo
modules = [(index, inspect.getmodule (stack [index] [0])) для индекса в обратном (диапазон (1, мин (stack_size, len (inspect.stack ()))))]
, чтобы получить модули.
– jake77
27 February 2018 в 14:37