Как да проверите валидните в момента типове в 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__) (вградените имена). Това са всички речници от име => обект, така че ги комбинирайте всички и получете обектите:

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] връща всички type 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 = builtins.__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