答案是type
你印象中的type是用来查看对象的类型的
li = []
type(li) # 得到list
对自定义的类是这样的
class Person:
pass
wuxianfeng = Person()
type(wuxianfeng) # __main__.Person
此处的wuxianfeng是一个Person类的实例
既然一切皆对象,那么Person的类型是啥呢?
type(Person) # type
https://docs.python.org/zh-cn/3.9/library/functions.html?highlight=type#type
class type(name, bases, dict, **kwds)
1. 传入一个参数时,返回 object 的类型。 返回值是一个 type 对象,通常与 object.__class__ 所返回的对象相同。
2. 推荐使用 isinstance() 内置函数来检测对象的类型,因为它会考虑子类的情况。
3. 传入三个参数时,返回一个新的 type 对象。 这在本质上是 class 语句的一种动态形式,
name 字符串即类名并会成为 __name__ 属性;
bases 元组包含基类并会成为 __bases__ 属性;如果为空则会添加所有类的终极基类 object。
dict 字典包含类主体的属性和方法定义;它在成为 __dict__ 属性之前可能会被拷贝或包装。
4. 下面两条语句会创建相同的 type 对象:
class X:
a = 1
X = type('X', (), dict(a=1))
5. 提供给三参数形式的关键字参数会被传递给适当的元类机制 (通常为 __init_subclass__()),相当于类定义中关键字 (除了 metaclass) 的行为方式。
6. 在 3.6 版更改: type 的子类如果未重载 type.__new__,将不再能使用一个参数的形式来获取对象的类型
稍作解释
a = 1
a.__class__
type(a) # 跟上面的结果是一样的, 但不能1.__class__哦~
s1 = 'a'
isinstance(s1,str) # True
isinstance(s1,(str,int,list)) # 一样也是True
class A:
pass
class B(A):
pass
b = B()
isinstance(b,B) # True
isinstance(b,A) # 也是True
# 但是type不一样,不会检查继承
type(b) == B # True
type(b) == A # False
上面是最简单的使用,最关键的来了,type传入三个参数时,返回一个新的 type 对象。 这在本质上是 class 语句的一种动态形式
# 在Pycharm上查看type的定义
class type(object):
"""
type(object_or_name, bases, dict) # 2种用法
type(object) -> the object's type # 上面讲的用法1
type(name, bases, dict) -> a new type # 创建动态类的另外一种方式
"""
1. name 字符串即类名并会成为 __name__ 属性;# 字符串类型
2. bases 元组包含基类并会成为 __bases__ 属性;如果为空则会添加所有类的终极基类 object。
3. dict 字典包含类主体的属性和方法定义;它在成为 __dict__ 属性之前可能会被拷贝或包装。# 这里可以填写类属性、类方式、静态方法,采用字典格式,key为属性名,value为属性值
官网案例
class X:
a = 1
# 等价于
X = type('X', (), dict(a=1))
我们做点拓展
示例1:一些典型的错误
type('A',,) # SyntaxError: invalid syntax
type('A',(),) # TypeError: type() takes 1 or 3 arguments
type('A',(),1) # TypeError: type.__new__() argument 3 must be dict, not int
示例2:类的创建
# 依旧是错误的示范
type('A',(),{}) # 相当于创建了一个类的名字叫A
a = A() # NameError: name 'A' is not defined 但你不能这么用
# 正确的
B= type('B',(),{})
b = B()
type(b) # __main__.B
# 诡异的(不推荐)
D = type('C',(),{})
x = C() # 哪个是对的?
y = D() # 哪个是对的?
D = type('C',(),{})
x = C() # 提示报错了,NameError: name 'C' is not defined
y = D() # 对的
type(y) # 结果是啥? __main__.C 你想到了吗?当然也还是可以理解的
# type('C',(),{}) 创建一个名叫C的类
# 但D这个变量接收了上面的返回值,C是没有这个变量的(不在内存中)
示例3:带继承的类的创建
class A:
pass
B = type('B',('A'),{}) # 这个错比较明显
# TypeError: type.__new__() argument 2 must be tuple, not str
class A:
pass
B = type('B',('A',),{})
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
# 其实错在你不能用'A',这是个str,实际上此处应该是一个类名
class A:
pass
B = type('B',(A,),{})
b = B() # 实例化没问题
print(B.__mro__) # mro也是ok的
# (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
示例4:带类属性的创建
C = type('C',(),{'name':'wuxianfeng'})
print(C.name) # 输出 wuxianfeng
示例5:带实例方法的创建
def say(self):
self.name = 'wuxianfeng'
print(f'calling method say, my name is {self.name}')
Person = type('Person',(),{'say':say})
wxf = Person()
wxf.say() # calling method say, my name is wuxianfeng
多一个例子(因为这是最常见的做法)
def run(self):
return 'calling run'
Foo = type('Foo',
(object,),
{'value':1,
'func':lambda self:'calling func',
'run':run})
foo = Foo()
print(foo.value) # 输出 1
result = foo.func() # 接收返回值‘calling func’
print(result) # 输出 calling func
print(foo.run()) # 输出 calling run
class创建类的本质就是用type创建,所以可以说python中所有类都是type创建的,包括整数、字符串、函数以及用户自定义的类
当type()只有一个参数时,其作用就是返回变量或对象的类型
当type()有三个参数时,其作用就是创建类对象
通过type添加的属性是类属性,不是实例属性
type就是Python的内建元类