【一】常用的魔法方法
【1】初始化对象的属性__init__
【二】元类
【1】什么是元类
- 一切源于一句话:Python中一切皆对象
- 八大基本数据类型是对象
- 类实例化得到的对象也是对象
- 其实类本身也是一种对象
class Human:
def __init__(self, name, age):
self.name = name
self.age = age
obj = Human('hqq', 21)
print(type(obj)) # <class '__main__.Human'>
print(type(Human)) # <class 'type'>
print(type(object)) # <class 'type'>
print(type(dict)) # <class 'type'>
- 通过查看每一种数据的数据类型,我们会发现都共同拥有一个类
- 这个类就是 type 我们也称之为元类
【2】产生类的两种方式
(1)直接关键字创建
- 语法
关键字(class) 类名(Student)继承的父类(默认是object):
# 类体代码
- 示例
class Human:
def __init__(self, name, age):
self.name = name
self.age = age
(2)通过 type 创建
def read():
...
Human = type('Human', (object,), {'name': 'hqq', 'age': 21, 'read': read})
print(type(Human)) # <class 'type'>
print(Human.__dict__)
【3】为什么要使用元类
- 元类可以控制类的创建,也就意味着我们可以高度定制类的具体行为
- 比如,当我们掌控了食品的生产过程,我们就可以在里面随便动手脚
【4】元类的基本使用
(1)需求
- 要求所有类的名字不能有下划线_
(2)思考
- 我们应该在哪里定制这些代码
- 类的产生过程也许我们还不熟悉
- 但是对象的产生过程,是通过类内的
__init__
方法实现的 - 那我们猜,在元类里面也有一个
__init__
方法
(3)基本使用
class MyType(type):
def __init__(cls, class_name, class_bases, class_dict):
print("MyType的__init__被调用,class_name是:", class_name)
print("MyType的__init__被调用,class_bases是:", class_bases)
print("MyType的__init__被调用,class_dict是:", class_dict)
super().__init__(class_name, class_bases, class_dict)
# 元类的使用区别于我们继承中使用父类的那种形式
# 元类的使用采用 metaclass 关键字声明
# 在前面学习 abc 模块的时候,我们也使用过类似的语法
# 【1】创建一个类
class MyClass(object, metaclass=MyType):
...
# 【2】初始化类
MyClass()
# MyType的__init__被调用,class_name是: MyClass
# MyType的__init__被调用,class_bases是: (<class 'object'>,)
# MyType的__init__被调用,class_dict是: {'__module__': '__main__', '__qualname__': 'MyClass'}
(4)进阶使用
- 限制类名不能有下划线
class MyType(type):
def __init__(cls, class_name, class_bases, class_dict):
print("MyType的__init__被调用,class_name是:", class_name)
print("MyType的__init__被调用,class_bases是:", class_bases)
print("MyType的__init__被调用,class_dict是:", class_dict)
# super().__init__(class_name, class_bases, class_dict)
if '_' in class_name:
raise NameError('类名不能有下划线')
class H_uman(metaclass=MyType):
def __init__(self, name, age):
self.name = name
self.age = age
obj = H_uman('hqq', 21)
'''
Traceback (most recent call last):
File "D:\python28\面向对象\导读.py", line 899, in <module>
class H_uman(metaclass=MyType):
File "D:\python28\面向对象\导读.py", line 896, in __init__
raise NameError('类名不能有下划线')
NameError: 类名不能有下划线
'''
- 类名有下划线有会抛出错误
【5】元类的进阶使用
(1)引入
- 当对象用括号调用时,必定会调用对象所属类的里面的
__call__
方法,并且得到对应的返回值 - 对象() ---->类里面的
__call__
方法 - 类()---->自定元类里面的
__call__
方法 - 自定元类()---->内置元类里面的
__call__
方法
class MyType(type):
def __init__(cls, class_name, class_bases, class_dict):
print("MyType的__init__被调用,class_name是:", class_name)
print("MyType的__init__被调用,class_bases是:", class_bases)
print("MyType的__init__被调用,class_dict是:", class_dict)
if '_' in class_name:
raise NameError('类名不能有下划线')
super().__init__(class_name, class_bases, class_dict)
def __call__(self, *args, **kwargs):
print('我被MyType里面的call方法触发了')
print(args, kwargs)
obj = super().__call__(*args, **kwargs)
return obj
class Human(metaclass=MyType):
def __init__(self, name):
self.name = name
obj = Human('hqq')
'''
MyType的__init__被调用,class_name是: Human
MyType的__init__被调用,class_bases是: ()
MyType的__init__被调用,class_dict是: {'__module__': '__main__', '__qualname__': 'Human', '__init__': <function Human.__init__ at 0x0000028A154340E0>}
我被MyType里面的call方法触发了
('hqq',) {}
'''
(2)定制对象产生过程
class MyType(type):
def __init__(cls, class_name, class_bases, class_dict):
print("MyType的__init__被调用,class_name是:", class_name)
if '_' in class_name:
raise NameError('类名不能有下划线')
super().__init__(class_name, class_bases, class_dict)
def __call__(self, *args, **kwargs):
print('我被MyType里面的call方法触发了')
print(args, kwargs)
if kwargs:
raise TypeError('必须用位置传参')
obj = super().__call__(*args, **kwargs)
return obj
class Human(metaclass=MyType):
def __init__(self, name):
self.name = name
obj = Human(name='hqq')
'''
Traceback (most recent call last):
File "D:\python28\面向对象\导读.py", line 912, in <module>
obj = Human(name='hqq')
^^^^^^^^^^^^^^^^^
File "D:\python28\面向对象\导读.py", line 901, in __call__
raise TypeError('必须用位置传参')
TypeError: 必须用位置传参
'''
【6】__new__
方法
__new__
用于产生空对象(类),相当于人的骨架__init__
用于实例化对象(类),相当于人的血肉
class MyType(type):
def __init__(cls, class_name, class_bases, class_dict):
print("MyType的__init__被调用,class_name是:", class_name)
if '_' in class_name:
raise NameError('类名不能有下划线')
super().__init__(class_name, class_bases, class_dict)
def __call__(self, *args, **kwargs):
print('我被MyType里面的call方法触发了')
print(args, kwargs)
if kwargs:
raise TypeError('必须用位置传参')
obj = super().__call__(*args, **kwargs)
return obj
def __new__(cls, *args, **kwargs):
print('我在MyType中被__new__执行了')
return super().__new__(cls,*args, **kwargs)
class Human(metaclass=MyType):
def __init__(self, name):
self.name = name
标签:__,name,print,面向对象,init,MyType,class,之元类 From: https://www.cnblogs.com/Hqqqq/p/17963205