文档:
使用三个参数,返回一个新的类型对象。这实际上是类语句的动态形式。 name 字符串是类名,并成为
__name__
属性; bases 元组逐项列出基类并成为__bases__
属性; dict 字典是包含类体定义的命名空间,并成为__dict__
属性。
在学习Python时,我发现这种类型的使用是“类声明的动态形式”,这看起来非常有趣和有用,我希望能更好地理解它。有人可以清楚地解释__name__
,__bases__
和__dict__
在班级中的作用,并举例说明type(name, bases, dict)
自身的作用。
答案 0 :(得分:9)
定义类时:
class Foo(Base1, Base2):
bar = 'baz'
def spam(self):
return 'ham'
Python基本上是这样做的:
def spam(self):
return 'ham'
body = {'bar': 'baz', 'spam': spam}
Foo = type('Foo', (Base1, Base2), body)
然后将Foo
添加到命名空间中,定义了class
语句。
class
语句下的块被执行,好像它是一个没有参数的函数,并且生成的本地命名空间(字典)构成了类体;在这种情况下,会形成一个包含'bar'
和'spam'
键的字典。
您可以通过将名称字符串,基类元组和带字符串键的字典传递给type()
函数来实现相同的结果。
一旦你开始探索元类(它们基本上是type()
的子类
,让你自定义类的创建方式),你会发现body
不 是一个普通的字典。 PEP 3115 - Metaclasses in Python 3将可能的值扩展为任何 dict(如),让您通过让增强的字典用于类体来实现各种有趣的类行为。例如,新的Python 3.4 enum
module使用OrderedDict()
instance来保留属性排序。
答案 1 :(得分:2)
__name__
是一个包含该类名称的字符串
__bases__
是当前类派生的类的元组
__dict__
是类中定义的所有方法和字段的字典。
type(name, bases, dict)
的用例是您希望在运行时动态生成类
想象一下,您想为数据库创建ORM,并且您希望自动生成表示数据库表的所有类。您知道这些类应该如何表现,但在检查数据库模式之前,您不知道它们的名称和字段。然后你可以使用这个函数来生成这些类。
答案 2 :(得分:1)
就像
一样a = Foo()
创建Foo
的实例并将其分配给a
,
Foo = type('Foo', (object,), {})
创建type
的实例并将其分配给Foo
。这不仅允许您动态创建类(类似于但不限于使用lambda
来创建函数),但它允许您(正确地)将type
视为函数,但作为一种类型本身。 type
的实例是一个类对象。 type.__new__
创建对象,type.__init__
初始化它,type.__call__
允许您将类用作可调用对象(这又是Foo()
创建和初始化{{1}实例的方式}})。
了解Foo
是您理解元类的方法。当您没有指定元类时,Python使用type
来创建类,就像您编写的那样(在Python 2.x中)
type
就像你可以继承普通类一样,你可以继承class Foo(object):
__metaclass__ = type
来创建你自己的元元类!
type
如果运行上述内容,则会在执行class mymetaclass(type):
def __new__(cls, name, bases, dict):
print "Creating a subclass of {0} named {1}".format(name, bases)
print "{0} will have the following attributes:".format(name)
for key in dict:
print " * {0}".format(key)
# This class statement is (roughly) identical to:
#
# def foo_init(self, x):
# self.y = x
#
# Foo = mymetaclass('Foo', (object,), { 'a': 3, '__init__': foo_init })
# (The class statement will also ensure that `__module__` and `__metaclass__`
# are in the dict passed to mymetaclass.__new__.)
class Foo(object):
__metaclass__ = mymetaclass
a = 3
def __init__(self, x):
self.y = x
语句时看到生成的输出,因为执行class
语句时会执行mymetaclass.__new__
。 / p>