繁体   English   中英

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

[英]How can I redefine the type() of instances of my Python class?

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

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

例如:

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

当实例作为字符串处理时,例如str(Test()) ,我可以设置自己的值。 我想要对type(Test())类似的东西:

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

(无效)

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

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

编辑:回答问题的另一部分:如果要覆盖类型,可以这样:

class A(object):
    pass

def x(x):
    return 'test'

__builtins__.type = x

print type(A())  # test

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

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

可能您需要类似:

import collections

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

实现此目的的一种方法是使用元类和定义类型。 这是一个简单的示例。

元类的定义和继承

# 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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM