元类及其相关

 什么是元类
    与普通类的区别
    有什么用
    如何使用

# code = """
# global s
# s = 1000
# a = 10
# print(a)
# """
#
# global_dic = {}
# local_dic = {}
#
# exec(code,global_dic,local_dic)
# print(global_dic)


# print(globals())
# print(local_dic)


# 要求你把你一个字符串中出现的名字 存储到一个名称空间中
# text = """
# def func():
#     print("func run")
# """
# l_dic = {}
# exec(text,{},l_dic)
# l_dic["func"]()

# """
#     什么是元类
#     一切皆对象
#
#
#     类的类就是元类
#     Person 类的元类是type   默认情况下所有类的元类都是type(object除外)
#
#
# """
# import abc  # 抽象类
#
# class Person(metaclass=type): # Person == type(..........)
#     def __init__(self,name,gender):
#         self.name = name
#         self.gender = gender
#
#     def say_hi(self):
#         print("hello im am %s  gender is %s" % (self.name,self.gender))
#
# p = Person("xx","xxx")
# # p.say_hi()
#
# # 函数对象
# # ls = [Person]
# # print(ls[0])
# #
# # def f1(cls):
# #     print(cls)
# #
# # f1(Person)
#
# print(type(p))
# print(type(Person)) # Person类是有type实例化产生的
#
#
# # 一个类需要包含三个部分
# # 类名称  它的父类 名称空间
#
# class_name = "myclass"
# class_bases = (object,)
# class_namespace = {}
#
# code = """
# school = "xxx"
# def hello(self):
#     print(self)
# """
#
# exec(code,{},class_namespace)
# print(class_namespace)
#
# # 创建类的另一种方式
# # 自己来实例化type类
# obj = type(class_name,class_bases,class_namespace)

# type类中肯定有__init__方法
#

class MyMetaClass(type):
    # 创建类时 就会自动执行元类中的init方法
    def __init__(self,class_name,bases,namespace):
        print("MyMetaClass init run")


# 产生一个空的类对象 在调用MyMetaClass中的__init__方法
class ClassA(metaclass=MyMetaClass): # ClassA = type("ClassA",(,),{})

    def __init__(self,name):
        self.name = name


# 创建出一个CLassA的类对象

class Test:
    def __init__(self):
        pass

t = Test() #实例化
# 1.创建一个对象的名称空间    空对象
# 2.执行__init__方法来为对象赋初始值

 

 

元类中init方法的执行:
class A:
    pass

# print(A)
# print(type(A))

namespace = {}
namespace["name"] = "jack"


cls = type("这是一个实例化Type产生的类",(object,),namespace)
#
# print(cls.name)
# print(A)


# 一个类是通过实例化type类产生
# 元类就是用于产生类的类

# 自定义一个元类
# class MyMeta(type):
#     # 创建B这个类对象的时候回自动执行
#     def __init__(self,a,b,c):
#         print("MyMeta init run")
#         print(self)
#         print(a)
#         print(b)
#         print(c)
#         self.school = "xxx"
#
# class B(metaclass=MyMeta): # B = MyMeta(B,"B",(object,),{......})
#     pass
#
# print(B.school)
#


# 必须保证类名大写开头
# class Meta1(type):
#     def __init__(self,clas_name,bases,namespace):
#         if not clas_name.istitle():
#             raise  TypeError("类名必须大写开头!")
# # 命名方式  大驼峰
# class person(metaclass=Meta1):
#     pass


class Meta2(type):
    def __init__(self,cls_name,bases,namespace):
        if not self.__doc__:
            raise  TypeError("必须包含类注释!!")


        super().__init__(cls_name,bases,namespace)


#
# 请编写代码 完成  限制一个类必须拥有类注释 否则 不允许创建类
class Animal(metaclass=Meta2):
    """
    asas
    """
    pass

print(Animal.__doc__)
print(Animal)

 

 

__call__方法的执行时机:

__call__
会在某个时间自动执行

class MyMeta(type):
    # 会在类对象 准备实例化产生对象时执行
    # 该函数可以控制实例化对象的过程
    def __call__(self, *args, **kwargs):
        print("Mymeta call run!")
        # print(self)
        # print(args)
        # print(kwargs)

        #无论你要添加什么功能  只要覆盖了__call__  就必须把下面两个步骤做了
        #1.需要创建一个对象
        obj = object.__new__(self)
        #2.调用对应init来初始化这个对象
        self.__init__(obj,*args,**kwargs)
        return obj

        # super().__call__(*args,**kwargs)

class Student(metaclass=MyMeta):
    def __init__(self,name):
        self.name = name
    pass

s = Student("xxx") # 是为了创建并实例化一个Student类的对象
print(s)


#__init__ 创建类对象的时候执行  控制类的创建过程

#__call__ 实例化产生对象时执行  控制对象的创建过程    单例模式

 

单例模式:

单例模式
    一种设计模式,MVVM MVC MTV
    常推荐书籍见设计模式

    要保证一个类只能有一个实例(单例)

    为什么这么设计?
        目的是为了节省内存开销
        如果两个对象的数据一模一样  就没有必要创建新对象  直接使用已有的即可

    场景:
        当一个类的所有实例数据都完全相同时 则应该设计为单例
        音乐播放器类 实例化产生播放器对象

    单例的实现方式:
        自定义元类 覆盖__cal__  添加判断逻辑 保证只能实例化一个对象

class MySingleton(type):
    obj = None
    def __call__(self, *args, **kwargs):
        if not self.obj:
            # 创建空对象
            obj = object.__new__(self)
            # 调用初始化方法
            self.__init__(obj, *args, **kwargs)
            self.obj = obj
        return self.obj


class Player(metaclass=MySingleton):
    # 默认为空
    obj = None

    def __init__(self):
        print("创建了一个播放器对象....")

    def play(self,path):
        self.stop()
        print("playing...",path)

    def stop(self):
        print("stop music")

    # 用于获取播放器对象
    @classmethod
    def get_player(cls):
        if not cls.obj:
            print("创建播放器...")
            cls.obj = cls()
        return  cls.obj

# p = Player("给我一杯忘情水.mp3")
# p.play()
#
#
# p.stop()
# p1 = Player("回首掏.mp3")
# p1.play()

# p = Player()
# p.play("一杯忘情水.")
#
#
p1 = Player.get_player()
p1.play("爱你一万年1.")


p2 = Player.get_player()
p2.play("爱你一万年2.")

# 上述代码 有bug  可以通过直接调用类 来产生新对象
Player().play("我的滑板鞋!")
 

 

存在元类时的属性查找顺序:

类自身属性 -->  父类--> object--> type

# class Meta(type):
#     s = 1000
#
#
# class A:
#     s = 1
#     pass
# class B(A,metaclass=Meta):
#     # s = 2
#     pass
#
# b = B()
# # b.s = 3
#
# print(b.s)
class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
    n=444

class Bar(object):
    # n = 333
    pass
class Foo(Bar):
    # n=222
    pass
class Teacher(Foo,metaclass=Mymeta):
    # n=111
    pass
print(Teacher.n)


 

 

你可能感兴趣的:(元类及其相关)