回顾
前面在学习Python编程:获取对象信息
知识时,我们已经知道了type()
函数。这个type()
函数既可以返回一个对象的类型,又可以创建出新的类型。type()
函数在传入一个参数时,返回的是对象所属的类型。这里特别要注意的是:通常所说的类比如动物类Animal、狗类Dog、猫类Cat、汽车类Car等,都是type的实例,说白了就是:动物类Animal、狗类Dog、猫类Cat、汽车类Car等,这些类的类型都是type类型。
type()
函数当传入三个参数时,可以动态创建新的class对象,也就是新类型。
一个入参:获取类型type(obj)
class type(obj)
官方解释:
With one argument, return the type of an object. The return value is a type object and generally the same object as returned by
object.__class__
.
意思大概是说:type函数传入一个参数时,返回结果是该对象的类型。返回值是type对象,和调用该对象的__class__
方法返回值一样。
三个入参:动态创建新的类实例 class type(name, bases, dict)
type()
函数当传入三个参数时,可以动态创建新的class对象,也就是新类型,如:通过该函数动态创建Fox类。 class type(name, bases, dict)的官方解释如下:
With three arguments, return a new type object. This is essentially a dynamic form of the class statement. The name string is the class name and becomes the
__name__
attribute; the bases tuple itemizes the base classes and becomes the__bases__
attribute; and the dict dictionary is the namespace containing definitions for class body and is copied to a standard dictionary to become the__dict__
attribute. For example, the following two statements create identical type objects。
要创建一个class对象,type()
函数依次传入3个参数:
1.新class的名称;
2.所要继承的父类的集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple
的单元素写法;
3.新class中的方法名称与函数可通过字典键值对一一绑定。例如:此参数传入:dict(my_eat=eat)
这里我们把函数eat绑定到方法名my_eat
上。
通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()
函数创建出class(即通常所说的类,这里类也是一个个的实例,类是type类型)。
看到这里,你会发现这与Java中的反射机制类似的:运行时动态创建的对象、绑定属性、方法等。
示例
我们说class
的定义是运行时动态创建的,而创建class的方法就是使用type()
函数。比如,我们可以通过type()函数创建出Fox类实例,而无需通过class Fox(object)...
的定义:
def my_eat(obj):
print("吃东西")
# 用type()创建类实例
Fox = type("Fox", (object,), dict(eat=my_eat))
f = Fox()
f.eat()
运行结果:
吃东西
正常情况下,我们都用class A...
来定义类,但是,type()
函数也允许我们动态创建出类来,也就是说,动态语言本身支持运行期动态创建类,这和静态语言有非常大的不同,要在静态语言运行期创建类,必须构造源代码字符串再调用编译器,或者借助一些工具生成字节码实现,本质上都是动态编译,会非常复杂。
metaclass
除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。
metaclass,直译为元类,简单的解释就是:当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。
但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。
连接起来就是:先定义metaclass,就可以创建类,最后创建实例。
所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。
metaclass是Python面向对象里最难理解,也是最难使用的魔术代码。正常情况下,你不会碰到需要使用metaclass的情况,所以,以下内容看不懂也没关系,因为基本上你不会用到。
示例
们先看一个简单的例子,这个metaclass可以给我们自定义的MyList增加一个add方法:
定义ListMetaClass,按照默认习惯,metaclass的类名总是以Metaclass结尾,以便清楚地表示这是一个metaclass:
# 定义元类ListMetaClass。metaclass是类的模板,所以必须从`type`类型派生:
class ListMetaClass(type):
def __new__(cls, name, bases, attrs):
attrs["add"] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)
# 自定义MyList类
class MyList(list, metaclass=ListMetaClass):
pass
my_list = MyList()
my_list.add(2)
my_list.add(4)
print(my_list)
运行结果:
[2, 4]
我们在定义MyList类的时候还要指示使用ListMetaClass
来定制类,正是通过传入关键字参数metaclass来指定的:class MyList(list, metaclass=ListMetaClass):
当我们传入关键字参数metaclass时,魔术就生效了,它指示Python解释器在创建MyList时,要通过ListMetaclass.new()来创建,在此,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。
__new__()
方法接收到的参数依次是:
- 当前准备创建的类的对象;
- 类的名字;
- 类继承的父类集合;
- 类的方法集合。
小结
本结知识,是python中生涩的知识点,难理解还几乎用不到,只做理解即可。
更多了解,可关注公众号:人人懂编程
微信公众号:人人懂编程
网友评论