Есть ли способ идентифицировать класс и объект - PullRequest
2 голосов
/ 08 августа 2011

Например, у меня есть класс

Class Cls:
   var 1 
   var 2

   def func(self):
      --- do some statement

Теперь я могу просто импортировать класс и создать объект

import Cls
clsObj = Cls()

Здесь Cls - это класс, а clsObj - это экземпляр класса.Есть ли какой-нибудь способ, которым я различаю их.

Спасибо

Ответы [ 4 ]

3 голосов
/ 08 августа 2011

I думаю это учитывает все случаи:

def isclass(obj):
    try:
        class_ = obj.__class__
    except AttributeError:
        # It's an old-style class
        return True
    try:
        class_.__class__
    except AttributeError:
        # It's an old-style instance
        return False
    # It's new-style
    return isinstance(obj, type)

Теперь давайте проверим его, чтобы убедиться, что он работает как положено / ожидаемо:

def test():
    class OldStyle: pass

    class NewStyle(object): pass

    def class_factory():
        return type("DynamicClass", (object,), {})

    class MetaClass(type):
        def __new__(mcls, *args):
            if args:
                return type(*args)
            return class_factory()

    class WithMeta(object):
        __metaclass__ = MetaClass
        def __call__(self):
            return self

    confusing = WithMeta()

    for name, obj in locals().items():
        templ = "{0:>26s} == {1!r:>5}, {2:>26s} == {3!r:>5}"
        print templ.format(
            "isclass({0})".format(name), isclass(obj),
            "isclass({0}())".format(name), isclass(obj()))

Вывод:

         isclass(OldStyle) ==  True,        isclass(OldStyle()) == False
         isclass(NewStyle) ==  True,        isclass(NewStyle()) == False
         isclass(WithMeta) ==  True,        isclass(WithMeta()) == False
        isclass(MetaClass) ==  True,       isclass(MetaClass()) ==  True
    isclass(class_factory) == False,   isclass(class_factory()) ==  True
        isclass(confusing) == False,       isclass(confusing()) == False

MetaClass, class_factory и confusing иллюстрируют дискуссию о том, что составляет класс в python, и показывают, как функция isclass обрабатывает эти случаи.

Re: agf

MetaClass не предназначен для такой реализации, поэтому ваши уловки, чтобы избежать ошибки, действительно просто запутывают проблему;правильнее было бы печатать «Ошибка» для MetaClass().

Вы или я написали MetaClass?Я имел в виду, что именно так и должны быть созданы.Я признаю, что нет никакого смысла иметь метакласс (или функцию фабрики классов), которая создает «один и тот же» класс при каждом его вызове, и, конечно, это сбивает с толку.Однако для этих конкретных целей я хотел бы проиллюстрировать, что метакласс создает класс при создании его экземпляра, и наличие множества аргументов для MetaClass() будет комбо-прерывателем в выходных данных.:) Так что в принципе я согласен с вами, но для этой конкретной цели я делаю это таким образом, и python позволяет мне это делать.

__call__ происходит ДО __new__ и что такое WithMeta(), confusing, и confusing() шоу корректно.

Если вы под словом «случается» подразумеваете «проанализированы, скомпилированы и связаны», тогда да, это происходит первым.Я не уверен, что понимаю, что ты здесь делаешь.Я согласен, что это правильно - конечно, это правильно, этот код был написан и запущен, и я опубликовал полученные результаты, так что это не может не быть правильным.Я не вижу, что с этим связано __call__.Не могли бы вы уточнить?

Вы на самом деле никогда не создавали WithMeta.Вы должны просто удалить это __call__ и показать ошибку для confusing()

Я вполне уверен, что я делаю создаю экземпляр WithMeta:

>>> WithMeta()
<isclass.WithMeta object at 0xb784574c>

Когда я пишу WithMeta(), python проверит, определено ли type(WithMeta).__new__, и это так, поэтому python затем предоставляет имя класса, базы и dict пространства имен в качестве аргументов для MetaClass.__new__().Он возвращает объект класса WithMeta, который создается путем вызова type с теми же аргументами.

С другой стороны, confusing() совпадает с type(confusing).__dict__["__call__"](confusing), который просто возвращает аргумент,так что confusing == confusing().

2 голосов
/ 08 августа 2011

Да, просто используйте встроенный тип (), который дает тип определенного объекта. Тип (clsObj) даст Instance в качестве ответа. Вы также можете проверить с помощью isinstance isinstance(clsObj,Cls) вернет True, тогда как isinstance(Cls,Cls) вернет False

1 голос
/ 08 августа 2011

Вы можете использовать свойство __class__ - clsObj.__class__

Из Python Tutorial :

Каждое значение является объектом, и поэтому имееткласс (также называется его типом).Хранится как object.__class__.

1 голос
/ 08 августа 2011

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

if type(obj) == type:
    # It's a class.
else:
    # It's an instance of a class.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...