更改用户创建的类上的type()函数的行为

时间:2016-11-12 04:00:44

标签: python python-2.7 class types

所以我想改变type()函数对我创建的类的工作方式。我将创建两个类,一个"旧样式"班级和一个"新风格"继承自object,以证明我的意思:

class Foo:
    pass

class Bar(object):
    pass

现在我将创建每个实例:

spam = Foo()
eggs = Bar()

如果我在每个类上使用type()函数会发生什么?

>>> type(spam)
<type 'instance'>
>>> type(eggs)
<class '__main__.Bar'>

我正在寻找改变这种行为的方法,以便它看起来更像是这样:

>>> type(spam)
<type 'foo'>

我已经看到很多其他对象这样做了(显然除了默认的数据类型)。例如:

>>> x = iter(['a', 'b', 'c'])
>>> type(x)
<type 'listiterator'>
>>> y = (i for i in range(10))
>>> type(y)
<type 'generator'>

这样的事情会非常接近,但如果我能提供帮助,我宁愿不让会员点在中间。 (是的,我使用它的代码将是导入的文件。)

>>> from itertools import *
>>> z = imap(pow, (2, 3, 4), (5, 2, 4))
>>> type(z)
<type 'itertools.imap'>

我确定这个问题的答案非常简单,但无论出于何种原因,我都无法弄清楚如何在此处提出搜索查询。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

使用单个调用时返回的type是对象的类。您在其中看到的字符串是“表示”,它是通过调用repr为该类生成的。本身 - 交互式提示调用repr。 Python对象通过定义__repr__方法来自定义它们的表示。

由于您要自定义类的__repr__而不是其实例,因此您必须在类的类本身中覆盖该方法。在Python中称为metaclass

所有Python“新样式”对象的基本元类都是type本身。 type不仅仅是一个返回对象类的简单函数 - 它实际上就是那个东西:所有东西的“基本元类”。 (旧式类具有不同的元类 - 但是它们你不应该使用旧式类来表达任何东西。完全没有。说真的。实际上,你现在应该使用Python 3 - 但如果你不是'改变,请忘记旧式的课程)

因此,要自定义类的类,您需要创建一个继承自type的新类。您将找到一些博客文章和文档,说明如何执行此操作并覆盖__new____init__。但在这种情况下,你 不需要改变类创建的实际行为 - 只需改变它们的表示方式。

你可以这样做:

class MyType(type):
   def __repr__(cls):
       return "<type '{}'>".format (cls.__name__)

 class Foo(object):
     __metaclass__ = MyType

它会按你的意愿工作。请注意,我将元类“__repr__”的参数设置为cls而不是self - 这是出于语义目的的jsut - 它将接收自身的“实例” - 但实例是一类。如果使用“自我”,它就会起作用。

最后,这也将改变您的实例默认情况下repr的呈现方式 - 而且这种表现可能会变得丑陋。如果您不喜欢它,只需为您的类编写__repr__方法(不仅仅是为了元类),进一步自定义它如何将其表示呈现为字符串形式。