在大多数帖子中,人们经常说,如果type
只有一个参数,那么它是一个内置函数,如果有三个参数,则是一个元类。
但在Python文档中,type
的签名为:
class type(object)
class type(name, bases, dict)
那么,这是否意味着type
是一个内置的类而不是内置的函数,即使它只提供了一个参数?
type
被称为“元类”,因为它是一个产生其他类(也称为类型)的类。它的行为就像一个普通的类。特别地,它具有相当于 Python 中这样的 __new__
方法:
class type(object):
def __new__(cls, *args):
num_args = len(args)
if num_args not in (1, 3):
raise TypeError('type() takes 1 or 3 arguments')
# type(x)
if num_args == 1:
return args[0].__class__
# type(name, bases, dict)
name, bases, attributes = args
bases = bases or (object,)
class Type(*bases):
pass
Type.__name__ = name
qualpath = Type.__qualname__.rsplit('.', 1)[0]
Type.__qualname__ = '.'.join((qualpath, name))
for name, value in attributes.items():
setattr(Type, name, value)
return Type
Class = type('Class', (), {'i': 1})
instance = Class()
print(type(instance)) # -> Class
print(instance.__class__) # -> Class
print(type(type(instance))) # -> type
print(Class.i) # -> 1
print(instance.i) # -> 1
__new__
返回的。 对于type
,__new__
始终返回一个类型对象(也称为类)。这是一个扩展了int
以使用-1
作为默认值而不是0
的类的示例:def Int__new__(cls, *args):
if not args:
return cls(-1)
return super(cls, cls).__new__(cls, *args)
Int = type('Int', (int,), {'__new__': Int__new__})
i = Int()
print(type(i)) # -> Int
print(i.__class__) # -> Int
print(type(type(i))) # -> type
print(i) # -> -1
j = Int(1)
print(j) # -> 1
type
的工作原理,可以查看 type_new 中的 C 代码。在那里你可以看到 (向下滚动几行) type(x)
是一个特殊情况,它会立即返回 x
的类型(也就是类)。当你执行 type(name, bases, dict)
时,将会调用类型创建机器。type(object)
type(type)
isinstance(object, object)
isinstance(type, object)
type(1)
type(type(1))
__new__
。这个问题涉及到内置的type
。鸭子类型是根据对象的行为而不是继承来分类的原则。与此无关。 - Paul Corneliustype
函数总是返回一个类型对象,它基本上是一个类。无论是单参数形式还是三参数形式,都是如此。在单参数情况下,返回的对象是参数的类型(类)。在三个参数的情况下,返回的对象是一个新的类型对象(类)。在两种情况下,返回的对象都可以用来实例化新的对象(类的实例)。type
的三个参数形式的常见用例。但是,还有其他方法可以创建可用作元类的类,并且type
的三个参数形式也有其他用途。int
并没有太大的区别,int
是一个内置函数,返回一个int
类型的对象。 int
也是一个类的名称,可以用来创建新的对象:>>> x = int()
>>> x
0
>>> type(x)
<class 'int'>
而且像类型一样,它有不止一种形式:
>>> y = int("A", 16)
>>> y
10
type
不是一个关键字。例如,for
、in
或as
是关键字。你不能将变量命名为for
,但可以将变量命名为type
(合法但强烈不建议!)。 - Paul Cornelius