所以我想改变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'>
我确定这个问题的答案非常简单,但无论出于何种原因,我都无法弄清楚如何在此处提出搜索查询。任何帮助将不胜感激。
答案 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__
方法(不仅仅是为了元类),进一步自定义它如何将其表示呈现为字符串形式。