课后练习 第一阶段:Python开发基础 day29 面向对象相关练习第一题
1.什么是元类
在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类,即元类可以简称为类的类
type是内置的一个元类,所有的类都是由type实例化得到,type类是产生所有类的元类
# 先class 一个类
class Person:
def __init__(self,name):
self.name = name
# 用刚才的类实例化一个对象
forever = Person('forever')
# 打印一下这个实例化对象的类型
print(type(forever)) # <class '__main__.Person'>
print(type(Person)) # <class 'type'>
运行结果:
<class 'main.Person'>
<class 'type'>
一切皆对象,对象也可以是类,从我们这打印的结果可以看出来,Person的元类就是type
2.Class底层原理实现
-
创建类的3个要素:类名,基类,类的名称空间
-
People = type(类名,基类,类的名称空间)
-
type(object_or_name, bases, dict)
-
通过type来直接产生类,不用class关键字了
代码:
dic = {}
exec(
'''
def __init__(self,name,age):
self.name = name
self.age = age
def ku(self):
print('forever kukudi')
''',{},dic
)
# 定义一个类
Forever = type('Forever',(object,),dic)
# 实例化一个对象
forever = Forever('forever',18)
# 取出类中的值
print(f'''forever`s name:{forever.name} forever`s age :{forever.age}''')
# 打印类的父类
print(Forever.__bases__)
运行结果:
forever`s name:forever forever`s age :18
(<class 'object'>,)
3.自定义元类控制类的产生
可以控制类名,可以控制类的继承父类,控制类的名称空间
自定义元类必须继承type,写一个类继承type 这种类都叫元类
代码如下:
class MyClass(type):
def __init__(self,name,bases,dic):
print(name)
if 'name' not in name.lower():
raise Exception('类名中没有name字段')
class MyDemo(object,metaclass=MyClass):
def __init__(self,name):
self.name = name
输出结果:
MyDemo
报错信息:
raise Exception('类名中没有name字段')
Exception: 类名中没有name字段
不报错的定义代码:
class Name(object,metaclass=MyClass):
def __init__(self,name):
self.name = name
运行结果:
Name
4.自定义元类控制类的执行过程
_call_
控制类的调用过程,实际上在控制:对象的产生
程序代码:
class MyClass(type):
def __call__(self, *args, **kwargs):
obj=object.__new__(self)
obj.__init__(*args, **kwargs)
obj.__dict__={ '_%s__%s'%(self.__name__,k):v for k,v in obj.__dict__.items()}
return obj
class MyDemo(object, metaclass=MyClass):
def __init__(self, name):
self.name = name
demo = MyDemo(name='forever')
print(demo.__dict__)
print(demo.name)
print(demo._MyDemo__name)
运行结果:
print(demo._MyDemo__name)
{'_MyDemo__name': 'forever'}
forever
print(demo.name)
Traceback (most recent call last):
{'_MyDemo__name': 'forever'}
File "F:/shpython11/pycharmwork/first_project/study_start/day29/homework.py", line 75, in
print(demo.name)
AttributeError: 'MyDemo' object has no attribute 'name'
5.属性查找
- 类的属性查找顺序:先从类本身中找--->mro继承关系去父类中找---->去自己定义的元类中找--->type中--->报错
- 对象的属性查找顺序:先从对象自身找--->类中找--->mro继承关系去父类中找--->报错
程序代码:
class Mymeta(type):
n=444
def __call__(self, *args, **kwargs): #self=<class '__main__.OldboyTeacher'>
obj=self.__new__(self)
# print(self.__new__ is object.__new__) #True
obj.__init__(*args, **kwargs)
return obj
class Bar(object):
# n=333
pass
# def __new__(cls, *args, **kwargs):
# print('Bar.__new__')
class Foo(Bar):
# n=222
pass
# def __new__(cls, *args, **kwargs):
# print('Foo.__new__')
class OldboyTeacher(Foo,metaclass=Mymeta):
# n=111
school='oldboy'
def __init__(self,name,age):
self.name=name
self.age=age
def say(self):
print('%s says welcome to the oldboy to learn Python' %self.name)
# def __new__(cls, *args, **kwargs):
# print('OldboyTeacher.__new__')
o=OldboyTeacher('forever',18) #触发OldboyTeacher的类中的__call__方法的执行,进而执行self.__new__开始查找
print(OldboyTeacher.n)