Как проверить действующие типы в Python

Предыстория: переход с R на Python с помощью numpy/scipy. Пытаюсь сделать небольшой модуль полезных функций. В частности, я пытаюсь создать рекурсивную проверку типа элемента.

Вопрос. Можно ли получить список текущих допустимых типов в среде Python, в которой вызывается функция?

Например, isinstance(1,int) вернет True, isinstance(1,str) вернет False, а isinstance(1,asdf) выдаст NameError: name 'asdf' is not defined, т.е. int и str определены, а asdf нет. Как я могу получить список определенных типов или имен, присутствующих в текущей среде Python, и отфильтровать их по типам?


person whearyou    schedule 04.08.2012    source источник
comment
Не имеет отношения, но это как бы противоречит утиной печати Python.   -  person jamylak    schedule 04.08.2012
comment
Что вы на самом деле пытаетесь сделать? Да, я читал recursive element type checker.   -  person phant0m    schedule 04.08.2012


Ответы (2)


В Python типы сами по себе являются обычными объектами. То есть, например,

type('hello') == str
type(5) == int
type(int) == type
type(type) == type

все True.

Итак, чтобы сделать это, найдите все переменные в области видимости, которые указывают на объекты типа type.

Чтобы получить все объекты в области действия посмотрите на оба dir() (что исключает встроенные имена, такие как int), и dir(__builtins__) (встроенные имена) locals() (переменные, определенные в текущей функции), globals() (переменные, определенные вне функций в текущем модуле) и vars(__builtins__) (встроенные имена). Это все словари из name => object, так что объедините их все и получите объекты:

objs = dict(vars(__builtins__), **dict(globals(), **locals())).values()

и фильтровать только типы:

types_in_scope = [o for o in objs if isinstance(o, type)]

Обратите внимание, что это только те переменные в области видимости, которые указывают на типы. Вполне возможно иметь ссылку на объект, тип которого не назначен ни одной переменной в области видимости. Например:

def foo():
    class Foo:
        pass
    return Foo()
x = foo()
person Mechanical snail    schedule 04.08.2012
comment
спасибо, но, похоже, не работает: / print [type(o) for o in objs] возвращает все типы str. поэтому types_in_scope возвращаются пустыми - person whearyou; 05.08.2012
comment
@whearyou: ой. Я забыл, что dict() просто возвращает имена, а не фактические объекты. Исправлено в редактировании. - person Mechanical snail; 05.08.2012
comment
спасибо, но stackoverflow.com/a/39858/1077083 очевидно, что ** - плохая идея и не работать с Python 3 или JPython или не 2.x CPython. вместо этого я сделал objs = встроенные.__dict__ objs.update(globals()) objs.update(locals()) И это работает! Так что спасибо тебе! Я выставил чек :) Вы захотите отредактировать свой ответ, хотя для будущих пользователей... - person whearyou; 06.08.2012
comment
@whearyou: это только в том случае, если ключи не являются строками. Но здесь ключи гарантированно будут строками, поскольку они являются именами переменных. - person Mechanical snail; 06.08.2012

Может быть, вы могли бы поискать модуль types? См. документацию здесь: http://docs.python.org/library/types.html. И вы также можете получить текущие переменные в своей программе, например:

In [9]: def spam():
            x=5
            y=6

In [10]: spam.func_code.co_varnames
Out[10]: ('x', 'y')

Надеюсь, это поможет, и вы можете начать. Извините, если совсем сбился с пути.

person Community    schedule 04.08.2012
comment
Я бы +1 за модуль types, но не уверен, почему вы включили хакерский код для получения имен переменных, это не часть вопроса. - person jamylak; 04.08.2012
comment
Op: как я могу получить список определенных типов или имен, присутствующих в текущей среде Python. Я подумал, что это может помочь OP получить список имен в текущей среде Python. - person ; 04.08.2012
comment
имена в текущей среде будут locals() или globals() - person jamylak; 04.08.2012
comment
@ Amit Начиная с Python 2.2 встроенные фабричные функции, такие как int() и str(), также являются именами для соответствующих типов. Теперь это предпочтительный способ доступа к типу вместо использования модуля типов. - person whearyou; 04.08.2012
comment
@jamylak locals() и globals() не возвращают все имена, так как не возвращают int или str - person whearyou; 04.08.2012