2.4.5 对象的创建和类的创建
本节目标:
了解通过一个类创建对象的过程
了解类创建的过程
在__init__
方法中,我们已经可以使用self
了,也就是说,__init__
的调用发生在对象创建之后。 但在Python中,我们有办法干预到对象创建本身。
Learning By Reading 难度:★★ 重要性:★★★★★
阅读材料,了解
__new__
。
同时,类也是对象,因此我们也有办法创建类对象。
Learning By Reading 难度:★★ 重要性:★★★
阅读材料,了解metaclass(元类)。
类也是对象,是一个type
类型的对象,所以我们看到在创建类的时候我们用到了type
类的__new__
方法。 这一点,类和其他对象没有区别。
我们先来玩一玩__new__
~
class MyTurtle(turtle.Turtle):
_all_turtles = {}
def __init__(self, name, *args, **kwargs):
self.name = name
MyTurtle._all_turtles[name] = self
@classmethod
def get_by_name(cls, name):
return cls._all_turtles[name]
ada = MyTurtle('ada')
if MyTurtle.get_by_name('ada') == ada:
print("找到了ada") # 输出
ada2 = MyTurtle('ada')
if MyTurtle.get_by_name('ada') == ada2:
print("又找到了ada") # 输出
if ada == ada2:
print("两只一样的ada") # 不输出
大家想一下就发现,ada = MyTurtle('ada')
和ada2 = MyTurtle('ada')
虽然都是创建了名字是ada
的小海龟, 但是只是名字相同,并不是真的是同一只。并且后一只会在MyTurtle._all_turtles
里面覆盖掉前面一只。
如果想要让每次MyTurtle('ada')
的时候都得到同一只小海龟应该怎么做呢?
class MyTurtle(turtle.Turtle):
_all_turtles = {}
def __new__(cls, name, *args, **kwargs):
if name not in cls._all_turtles:
cls._all_turtles[name] = super(MyTurtle).__new__(*args, **kwargs)
return cls._all_turtles[name]
def __init__(self, name):
self.name = name
ada = MyTurtle('ada')
ada2 = MyTurtle('ada')
if ada == ada2:
print("两只一样的ada") # 输出
__new__
告诉Python如何创建MyTurtle
类的对象, ada = MyTurtle('ada')
的时候,Python发现ada
这个名字不在MyTurtle._all_turtles
里面,于是返回了一个新创建的海龟对象(用super(MyTurtle).__new__
)。 ada2 = MyTurtle('ada')
的时候,就直接返回储存在MyTurtle._all_turtles
中的ada
了。
我们之前介绍过,Python中的类也是对象,每个类都是type
对象。 type
类就是用来创建类对象的,也是通过__new__
方法。
class MyTurtle(turtle.Turtle, AnotherClass, AnotherAnotherClass):
_all_turtles = {}
def __init__(self, name):
self.name = name
这样定义一个类,等价于
def __init__(self, name):
self.name = name
MyTurtle = type('MyTurtle', (turtle.Turtle, AnotherClass, AnotherAnotherClass), {'_all_turtles': {}, '__init__': __init__})
后一种方法直接用type
类生成了一个类。 我们看到type
带了三个参数,第一个是一个字符串表示类名,第二个是一个tuple
表示继承哪些类,第三个是一个字典表示所有的属性和方法。
Last updated