如何重新定义Python类实例的类型()?

时间:2016-02-07 13:30:10

标签: python python-2.7 class types instance

我正在做一些调试,需要确保我的类的实例具有特定类型,例如<type 'list'>,当type()被调用时。

另一个选项是重新定义type(),以便在我的类的实例传递给它时返回不同的值。

例如:

class Test:
    def __str__(self):
        return 'anything'

允许我在将实例视为字符串时设置自己的值,例如str(Test())。我想要type(Test())的类似内容:

class Test:
    def __type__(self):
        return type([])

(无效)

3 个答案:

答案 0 :(得分:0)

你可以,但我不建议这样做:

print_r

如果完全更改类型而不是名称,则对象的类型实际上会发生变化。

class A(object):
    def __init__(self):
        self.__class__.__name__ = 'B'

print type(A())  # <class 'B'>
print type(A()) == B  # False, since it's actually not a type B
print type(A()).__name__ == 'B'  # True, since the name is 'B'

修改:回答问题的其他部分:如果要覆盖类型,可以这样做:

class B(object):
    def x(self):
        return 'b'

class A(object):
    def __init__(self):
        self.__class__ = B
    def x(self):
        return 'a'

print A().x()  # b

答案 1 :(得分:0)

我的印象是你试图做错事,可能是因为你以前的经历是使用静态类型语言。

在python中你永远不应该检查类型,你应该检查行为。

可能你需要这样的东西:

import collections

if isinstance(theElement, collections.Iterable):
    # iterable
else:
    # not iterable

答案 2 :(得分:0)

实现此目的的一种方法是使用元类和定义类型。这是一个如何做到这一点的简单例子。

元类定义和继承

# Meta class
class TypeClass(type):
        def __new__(cls, *args, **kwargs):
                return super(TypeClass, cls).__new__(cls, *args, **kwargs)

        def __init__(self, *args, **kwargs):
                super(TypeClass, self).__init__(*args, **kwargs)


# Class directly inheriting from the meta class.
class ObjectClass(metaclass=TypeClass):
        pass


# Class that has indirectly inherited from the meta class.
class TestClass(ObjectClass):
        pass

<强>测试

让我们测试TypeClass

test = TypeClass
print("mro: {} \ntype: {} \nrepr: {}".format(
          test.__mro__,
          type(test),
          repr(test)
      ))

mro: (<class '__main__.TypeClass'>, <class 'type'>, <class 'object'>) 
type: <class 'type'> 
repr: <class '__main__.TypeClass'>

现在让我们测试ObjectClass

test = ObjectClass
print("mro: {} \ntype: {} \nrepr: {}".format(
          test.__mro__,
          type(test),
          repr(test)
     ))

显示器:

mro: (<class '__main__.ObjectClass'>, <class 'object'>) 
type: <class '__main__.TypeClass'> 
repr: <class '__main__.ObjectClass'>

最后,让我们测试一下TestClass

test = TestClass

print("mro: {} \ntype: {} \nrepr: {}".format(
          test.__mro__, 
          type(test), 
          repr(test)
      ))

显示器:

mro: (<class '__main__.TestClass'>, <class '__main__.ObjectClass'>, <class 'object'>) 
type: <class '__main__.TypeClass'> 
repr: <class '__main__.TestClass'>

回答问题

所以,这是你问题的答案。虽然,如果你说为什么要这样做会很有用。也许有更好的方法来实现你在这里尝试实现的目标!

class TypeClass(list):
        def __new__(cls, args):
                return super(TypeClass, cls).__new__(cls, args)

        def __init__(self, args):
                super(TypeClass, self).__init__(args)


# class ObjectClass(metaclass=TypeClass):
#         pass


class TestClass(TypeClass):
        pass


test = TestClass
print("mro: {} \ntype: {} \nrepr: {}".format(
        test.__mro__,
        type(test),
        repr(test)
      ))


tests = {
        'test1': isinstance(TestClass, type(list)),
        'test2': isinstance(TestClass, list),
        'test3': type(TestClass) is type(list),
        'test4': type(TestClass) is list,
        'test5': type(TestClass) is type([]),
        'test6': type(TestClass) == type(list),
        'test7': type(TestClass) == type([]),
        'test8': type(TestClass) == type(type([]))
}

print('\n', *[item for item in tests.items()])

显示:

mro: (<class '__main__.TestClass'>, <class '__main__.TypeClass'>, <class 'list'>, <class 'object'>) 
type: <class 'type'> 
repr: <class '__main__.TestClass'>

('test3', True) ('test6', True) ('test4', False) ('test7', False) ('test5', False) ('test2', False) ('test1', True) ('test8', True)