Идентификация, что переменная является модернизированным классом в Python?

Я использую Python 2.x, и я задаюсь вопросом, существует ли способ сказать, является ли переменная модернизированным классом? Я знаю что, если это - класс старого стиля, который я могу сделать следующее для обнаружения.

import types

class oldclass:
  pass

def test():
  o = oldclass()
  if type(o) is types.InstanceType:
    print 'Is old-style'
  else:
    print 'Is NOT old-style'

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

import inspect

def newclass(object):
  pass

def test():
  n = newclass()
  if inspect.isclass(n):
    print 'Is class'
  else:
    print 'Is NOT class'
  if inspect.isclass(type(n)):
    print 'Is class'
  else:
    print 'Is NOT class'
  if inspect.isclass(type(1)):
    print 'Is class'
  else:
    print 'Is NOT class'
  if isinstance(n, object):
    print 'Is class'
  else:
    print 'Is NOT class'
  if isinstance(1, object):
    print 'Is class'
  else:
    print 'Is NOT class'

Так там должен так или иначе сделать что-то вроде этого? Или все находится в Python просто классом и нет никакого способа обойти это?

14
задан Community 23 May 2017 в 10:30
поделиться

4 ответа

Думаю, вы спрашиваете: «Могу ли я проверить, был ли класс определен в коде Python как класс нового стиля?». Технически простые типы, такие как int , являются классами нового стиля, но все же можно отличить классы, написанные на Python, от встроенных типов.

Вот кое-что, что работает, хотя это немного похоже на взлом:

def is_new_style(cls):
    return hasattr(cls, '__class__') \
           and \
           ('__dict__' in dir(cls) or hasattr(cls, '__slots__'))


class new_style(object):
    pass

class old_style():
    pass

print is_new_style(int)
print is_new_style(new_style)
print is_new_style(old_style)

Вывод из Python 2.6:

False
True
False

Вот другой способ сделать это:

def is_new_style(cls):
    return str(cls).startswith('<class ')
7
ответ дан 1 December 2019 в 15:21
поделиться

Я считаю, что этого достаточно:

def is_new_style_class(klass):
    return issubclass(klass, object)

def is_new_style_class_instance(instance):
    return issubclass(instance.__class__, object)

Как правило, для ваших целей вам нужна только функция is_new_style_class. Все, что не является классом, вызовет TypeError, поэтому вы можете обновить его до:

def is_new_style_class(klass):
    try:
        return issubclass(klass, object)
    except TypeError:
        return False

Примеры:

>>> class New(object): pass
... 
>>> is_new_style_class(New)
True
>>> class Old: pass
... 
>>> is_new_style_class(Old)
False
>>> is_new_style_class(1)
False
>>> is_new_style_class(int)
True

int, будучи типом, по определению является классом нового стиля (см. Объединение типов и классов в Python 2.2), или, если хотите, классы нового стиля являются типами по определению.

2
ответ дан 1 December 2019 в 15:21
поделиться

Дело не в том, что «все является классом»: вы сталкиваетесь с тем, что «все является объектом » (то есть каждая вещь (в новом стиле) происходит от «объекта») .

Но классы нового стиля сами по себе являются «типом» (фактически, они были введены для объединения классов и типов). Так что вы можете попробовать проверить

import types

type(o) == types.TypeType

Решает ли это вашу проблему?

1
ответ дан 1 December 2019 в 15:21
поделиться

Проверить наличие классов старого стиля очень просто. Просто проверьте, что type (cls) - это types.ClassType . Также легко проверить наличие классов нового стиля, isinstance (cls, type) . Обратите внимание, что встроенные типы также являются классами нового стиля.

Кажется, нет тривиального способа отличить встроенные модули от классов, написанных на Python. Классы нового стиля с __slots__ также не имеют __dict__, как и int или str . Проверка соответствия str (cls) ожидаемому шаблону завершается ошибкой, если метакласс классов переопределяет метод __str__. Некоторые другие способы, которые также не работают:

  • cls .__ module__ == '__builtin __' (вы можете переназначить __module__ для классов)
  • not any (value is cls для значения в vars (__ builtins __). Values ()) (вы можете добавить что-нибудь в модуль __builtin__).

Тот факт, что унификация встроенных и определяемых пользователем типов настолько хороша, что их различение является нетривиальной проблемой, должен означать для вас основную мысль. Вам действительно не нужно различать их. Неважно, что это за объект, если он реализует ожидаемый протокол.

-1
ответ дан 1 December 2019 в 15:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: