【一】内置方法补充
1)__call__
# __call__:当类()或对象()调用时触发
class Eg:
def __init__(self):
print('执行__init__')
def __call__(self, *args, **kwargs):
print('执行__call__')
obj = Eg() # 执行__init__
obj() # 执行__call__
# 校验当前对象是否可被调用
# 类本身是可以被任意调用的
print(callable(Eg)) # True
# 对象本身是不具备直接被调用的功能的,想让对象也能被调用就必须重写 __call__
print(callable(obj)) # True
2)isinstance(obj,cls)
- 判断当前对象是否是某一个类的类型
class Animal:
...
class Dog:
...
animal = Animal()
dog = Dog()
# 判断当前对象是否是指定类型的对象
res_animal = isinstance(dog, Animal)
print(res_animal) # False
res_dog = isinstance(dog, Dog)
print(res_dog) # True
3)issubclass(sub,super)
- 校验一个类是否是属于另一个类的子类
class Animal:
...
class Dog(Animal):
...
class Cat:
...
print(issubclass(Dog, Animal)) # True
print(issubclass(Cat, Animal)) # False
【二】元类
1)概念
- 元类是所有类的基础,包括object
- 八大基本数据类型、类实例化得到的对象、类本身均是一种对象
- 类就是type,即元类
2)元类的创建方法
1.直接用关键字创建
class 类名(继承的父类):
类体代码
class Student:
def __init__(self, name):
self.name = name
print(type(Student))
# <class 'type'>
print(Student.__dict__)
# {'__module__': '__main__', '__init__': <function Student.__init__ at 0x000002A1E21C4400>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
2.通过type创建
类名 = type('类名',(父类1,父类2),名称空间字典)
Student = type('Student', (object,), {'name': 'diva'})
print(Student)
# <class '__main__.Student'>
print(type(Student))
# <class 'type'>
print(Student.__dict__)
# {'name': 'diva', '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
3)元类使用
1.优势
- 元类可以控制类的创建,即我们可以高度定制类的具体行为
2.元类的基本使用
# 创建元类
class MyType(type):
def __init__(cls, class_name, class_bases, class_name_space):
# cls 是当前类的本身
print(f'cls:{cls}')
# cls:<class '__main__.MyClass'>
# class_name 当前类的类名
print(f'class_name:{class_name}')
# class_name:MyClass
# class_bases 当前类的父类
print(f'class_bases:{class_bases}')
# class_bases:()
# class_name_space 当前类的名称空间
print(f'class_name_space:{class_name_space}')
# class_name_space:{'__module__': '__main__', '__qualname__': 'MyClass'}
super().__init__(class_name, class_bases, class_name_space)
# 创建一个继承元类的类
# metaclass 指定元类
class MyClass(metaclass=MyType):
...
4)元类进阶使用(控制类名首字母大写)
# 控制当前类名必须首字母大写!首字母不大写就报错!
# 【1】创建元类
class MyType(type):
def __init__(cls, class_name, class_bases, class_name_space):
super().__init__(class_name, class_bases, class_name_space)
# istitle : 首字母必须大写其他必须全小写
if not class_name.istitle():
raise TypeError(f'{class_name}首字母必须大写!')
# 【2】创建一个继承元类的类
class Eg(metaclass=MyType):
...
# 不报错
class eg(metaclass=MyType):
...
# 报错
5)元类__call__
补充
class MyType(type):
def __init__(cls, class_name, class_bases, class_name_space):
print('MyType的__init__')
super().__init__(class_name, class_bases, class_name_space)
def __call__(self, *args, **kwargs):
print('MyType的__call__')
obj = super().__call__(*args, **kwargs)
print('***')
return obj
class Student(metaclass=MyType):
def __init__(self, name):
print('MyClass的__init__')
self.name = name
def __call__(self, *args, **kwargs):
print('MyClass的__call__')
# MyType的__init__
st1 = Student('diva')
# MyType的__call__
# MyClass的__init__
# ***
print(st1())
# MyClass的__call__
# None
print(st1.name)
# diva
- 高度定制 类的产生过程
- 编写元类里面的
__init__
- 编写元类里面的
- 高度定制 对象的产生过程
- 编写元类里面的
__call__
- 编写元类里面的
【三】元类结合__new__
__new__ : 产生空对象(类),用来生成骨架
__init__ : 实例化对象(类),骨架添加血和肉
1)类中的__new__
class MyClass(object):
def __init__(self, name, age):
print(f"给当前 MyClass 类的对象初始化属性的时候会触发 __init__")
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print(f"当前 MyClass 类的对象被调用的时候会触发 __call__")
return f'当前 MyClass 类 的 __call__ 的返回值 :>>>> {self.name}'
# 【三】花骨架 有了骨架才能上色
def __new__(cls, *args, **kwargs):
print(f"给当前 MyClass 类的对象创建骨架的时候会触发 __new__")
# 【1】当前类本身
print(f" MyClass 类 的 __call__ 的 cls :>>>> {cls}")
# MyClass 类 的 __call__ 的 cls :>>>> <class '__main__.MyClass'>
# 【2】当前类初始化传的位置参数
print(f" MyClass 类 的 __call__ 的 args :>>>> {args}")
# MyClass 类 的 __call__ 的 args :>>>> ('dream',)
# 【3】当前类初始化传的关键字参数
print(f" MyClass 类 的 __call__ 的 kwargs :>>>> {kwargs}")
# MyClass 类 的 __call__ 的 kwargs :>>>> {'age': 18}
# 【四】调用父类 的 object 的 __new__ 帮我搭建好骨架
obj = object.__new__(cls)
# 【1】查看当前返回值发现是一个对象类型
print(f'obj :>>>> {obj}')
# obj :>>>> <__main__.MyClass object at 0x000001984B032340>
# 【2】发现当前对象的民称空间是空的
print(f'obj.__dict__ :>>>> {obj.__dict__}')
# obj.__dict__ :>>>> {}
# 【五】调用自己的 __init__ 方法 初始化属性
obj.__init__(*args, **kwargs)
# 【】给自己的名称空间初始化属性
print(f'obj.__dict__ :>>>> {obj.__dict__}')
# obj.__dict__ :>>>> {'name': 'dream', 'age': 18}
return obj
# MyClass 相当于给你一张纸
# 【一】类() 调用 ---> 一定会触发 __init__ 初始化对象的属性 # __init__ 给你人体骨架上个色
# 【二】在调用 __init__ 之前要调用 __new__ # __new__ 相当于将你人体的骨架搭建好
m = MyClass('dream', age=18)
# 【六】完成对象属性的初始化
print(m.name)
2)元类中的__new__
class MyType(type):
def __init__(cls, class_name, class_bases, class_name_space):
print(f"给当前 MyType 类的对象初始化属性的时候会触发 __init__")
super().__init__(class_name, class_bases, class_name_space)
def __call__(self, *args, **kwargs):
# 得到一个空的对象
obj = super().__call__(*args, **kwargs)
return obj
# 【三】花骨架 有了骨架才能上色
def __new__(cls, *args, **kwargs):
print(f"给当前 MyType 类的对象创建骨架的时候会触发 __new__")
# 【1】当前类本身
print(f" MyType 类 的 __call__ 的 cls :>>>> {cls}")
# MyType 类 的 __call__ 的 cls :>>>> <class '__main__.MyType'>
# 【2】当前类初始化传的位置参数
print(f" MyType 类 的 __call__ 的 args :>>>> {args}")
# MyType 类 的 __call__ 的 args :>>>> ('MyClass', (), {'__module__': '__main__', '__qualname__': 'MyClass', '__init__': <function MyClass.__init__ at 0x0000016DE31ACAF0>, '__call__': <function MyClass.__call__ at 0x0000016DE31ACB80>})
# 【3】当前类初始化传的关键字参数
print(f" MyType 类 的 __call__ 的 kwargs :>>>> {kwargs}")
# MyType 类 的 __call__ 的 kwargs :>>>> {}
# 【四】让你的父类帮你大骨架
obj = type.__new__(cls, *args, **kwargs)
print(f'obj :>>>> {obj}')
# obj :>>>> <class '__main__.MyClass'>
print(f'obj.__dict__ :>>>> {obj.__dict__}')
# obj.__dict__ :>>>> {'__module__': '__main__', '__init__': <function MyClass.__init__ at 0x0000023A62C2CB80>, '__call__': <function MyClass.__call__ at 0x0000023A62C2CC10>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}
return obj
class MyClass(metaclass=MyType):
def __init__(self, name, age):
print(f"给当前 MyClass 类的对象初始化属性的时候会触发 __init__")
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print(f"当前 MyClass 类的对象被调用的时候会触发 __call__")
return f'当前 MyClass 类 的 __call__ 的返回值 :>>>> {self.name}'
# MyClass 相当于给你一张纸
# 【一】类() 调用 ---> 一定会触发 __init__ 初始化对象的属性 # __init__ 给你人体骨架上个色
# 【二】在调用 __init__ 之前要调用 __new__ # __new__ 相当于将你人体的骨架搭建好
m = MyClass('dream', age=18)
# 【六】完成对象属性的初始化
print(m.name)
标签:__,21,面向对象,init,call,print,class,name
From: https://www.cnblogs.com/Mist-/p/18184450