面向对象,元类,控制类,对象的创建

"""

call

调用的意思 ​ 在在对象被调用时 执行

函数 类

自定义元类 的目的 ​ 1.可以通过call 来控制对象的创建过程 ​ 2.可用控制类的创建过程 """

自定义一个元类 元类也是一个类 但是需要继承type
class MyMeta(type):

self 表示要创建对象的那个类(Person) *args是调用Person类时传入的参数

•  def __call__(self, *args, **kwargs):

•      print("MyMte中的 call run'")

print(*args)       #Person的参数

print(self)                 #person 类

下面的三步是固定写法 一个模板 只要你需要控制对象的创建过程 就应该先把模板写出来

1.创建空对象

•      obj = object.__new__(self)

2.调用初始化方法

•      self.__init__(obj,*args,**kwargs)

3.得到一个完整的对象

•      return obj

修改Person类的元类为MyMeta

class Person(metaclass=MyMeta):

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

•  def __call__(self, *args, **kwargs): #程序运行的就会自动运行
•      print("call run...")

调用Person这个对象时 执行的是 Person的类(type)中__call__ 方法

p = Person("张三",80)

print(p)

当调用对象时 会执行该对象所属类中的__call__方法

p()

print(p.name)
print(p.age)

 

练习:

class My(type):
  obj = None
  def __call__(self, *args, **kwargs):
      if not My.obj:
          print('yes')
          obj = object.__new__(self)
          self.__init__(obj,*args, **kwargs)
          My.obj = obj
      return My.obj

class Orange(metaclass=My):
  def __init__(self,name,type_1,price):
      self.name = name
      self.type = type_1
      self.price = price
  def forma(self):
      print(self.__dict__)
o1 = Orange('金水橘','橘子',40)
o1.forma()

 

练习2:

class CarMeta(type):
•  def __call__(self, *args, **kwargs):

  if len(args) < 3:
      raise ValueError("必须包含三个参数.....")
  obj = object.__new__(self)
  self.__init__(obj,*args,**kwargs)

  if not("production_date" in obj.__dict__  
  and "engine_number" in obj.__dict__ 
  and "capacity" in obj.__dict__):
      raise ValueError("必须包含 生产日期,发动机编号,载客容量")
  return obj


class BigCar(metaclass=CarMeta):
•  def __init__(self,production_date,engine_number,capacity):
•      self.production_date = production_date
•      self.engine_number = engine_number
•      self.capacity = capacity

c = BigCar("2018 12 21","e-1-3-q-f",5)
print(c)







要控制类的创建过程 只要找到类所属的类 中的init即可

class MyMeta(type):

1. self 刚建出来的类
2. 第二个 类的名字
3. 第三个 类的父类们 元组
4. 第四个 这个类传进来的名称空间

  def __init__(self ,class_name ,bases ,namespace):
      print("============================")

# print(self.__dict__)

# 我要控制 类的名字 必须 是大写开头

      if not class_name.istitle():
          print("类名 必须大写开头...... ")

# 该代码是主动抛出异常

          raise TypeError("类名 必须大写开头...... ")

# 要空类的创建 必须包含__doc__这个属性

      if not self.__doc__:
          raise TypeError("类中必须有文档注释.....")

      pass

class Student(metaclass=MyMeta):   # Student = MyMeta("Student",(object,),{})
  """
      这是文档注释 可以通过__doc__来获取
      这是一个学生类
  """

# 在类的__init__中可以控制该类对象的创建过程

  def __init__(self ,name):
      print("-----------------------")
      print(self.__dict__)
      self.name = name

print(Student.__doc__)

 

元类使用总结:

""" 元类是用于创建类的类 学习元类是为了 能控制类的创建过程 以及 类实例化对象的过程

一. 控制类的创建过程 ​ 1.创建一个元类 (需要继承type) ​ 2.覆盖init方法 该方法 会将新建的类对象 类名 父类们 名称空间 都传进来 , ​ 可以利用这些信息在做处理 ​ 3.对于需要被控制的类 需要指定metaclass 为上面的元类

 

二. 控制类实例化对象的过程 ​ 1.创建一个元类 (需要继承type) ​ 2.覆盖call方法 会将 正在实例化对象的类 调用类是传入的参数 都传进来 ​ 3.在call方法中 必须要先编写模板代码 ​ 3.1创建空对象 ​ 3.2调用类的init方法来初始化这个空对象 ​ 3.3返回该对象 ​ 4.加入你需要控制的逻辑

类的三个组成部分 类名 父类们 名称空间

元类 -> 实例化产生 -> 类 -> 实例化产生 -> 对象

"""

 

练习:

组合创建类的创建对象的技巧

class My(type):
  def __init__(self,a,b,c):
      if not a.istitle():
          print('首字母注意大写')
          raise TypeError('类名开头必须大写')
      if not a.__doc__:
          print('注释为空')
          raise TypeError('请添加注释')
  obj = None
  def __call__(self, *args, **kwargs):
      print('yes')
      if not My.obj:
          obj = object.__new__(self)
          self.__init__(obj,*args, **kwargs)
          My.obj = obj
      return My.obj
class Tree(metaclass=My):
  def __init__(self,name,age):
      self.name = name
      self.age = age
  def breath(self):
      print('这颗%s的%s的大树很粗壮'%(self.age,self.name))
t1=Tree('衫树',30)
print(t1)
t2=Tree('衫树',30)
print(t2)
t1.breath()




单例

""" ​ 单例模式 ​ 一种设计模式(套路)

单个实例 ​ 一个类如果只有一个实例 那么该类称之为单例

为什么需要单例

当要处理的数据全部相同时,比如打印机复印文件时

"""

代码1:


class Printer():
  """
  这是一个单例类 请不要直接实例化 使用get方法来获取实例
  """

  obj = None
  def __init__(self,name,brand,type):
      self.name = name
      self.brand = brand
      self.type = type

  def printing(self,text):
      print("正在打印 %s" % text)

 

以下三个对象 的数据完全相同 但是却 占用三分内存空间

p1 = Printer("ES005","爱普生","彩色打印机")

p2 = Printer("ES005","爱普生","彩色打印机")

p3 = Printer("ES005","爱普生","彩色打印机")

 

用类调用:

obj = None           #定义了类的属性
  @classmethod
  def get_printer(cls):
      if not cls.obj:
          obj = cls("ES005","爱普生","彩色打印机")
          cls.obj = obj
          print("创建了新的对象")

      return cls.obj

 

通过该方法来获取对象 可以保证只有一个对象

 

p = Printer.get_printer()
print(p)

p = Printer.get_printer()
print(p)

p = Printer.get_printer()
print(p)

p = Printer.get_printer()
print(p)
# 内存地址都相同

 

通过该方法来获取对象 可以保证只有一个对象

但是这还不够 因为 还是可以通过调用类产生新对象

就应该使用元类 来控制实例化的过程 call

call 中编写代码 保证每次调用call 都返回同一个实例 即可

 

现在要处理问题就是 如何能够限制该类 只能实例化一个对象

元类

代码2:

class My(type):
  obj = None
  def __call__(self, *args, **kwargs):
      if not My.obj:
          obj = object.__new__(self)
          self.__init__(obj, *args, **kwargs)
          My.obj = obj
      return My.obj
       
class Printer(metaclass=My):
  """
  这是一个单例类 请不要直接实例化 使用get方法来获取实例
  """
  def __init__(self,name,brand,type):
      self.name = name
      self.brand = brand
      self.type = type
def printing(self,text):
      print("正在打印 %s" % text)
       
p1 = Printer("ES005","爱普生","彩色打印机")
p2 = Printer("ES005","爱普生","彩色打印机")

print(p1)
print(p2)
#内存地址全部一样
p1.printing("一本小说....")

元类的思想就是控制对象,所有对象全部都要在call走一遍,才能返回到类里使用。因此在第一次经过元类时,元类就通过赋值给固定死了,以后都不会再初始化了。

 

 

 

了解:

代码1:

class MyMeta(type):

# 用于新建类对象

  def __new__(cls, *args, **kwargs):
      print("new run")

print(MyMeta)

print(*args)

调用type通过的__new__方法来创建一个空的类对象 已经将三个组成部分都放到类对象中了

      res = type.__new__(cls,*args)
      return res

  def __init__(self,class_name,bases,namespace):
      print("init run")
      print(self)



class Student(metaclass=MyMeta):
  pass

print(Student)

""" new 与 init的区 newinit先执行 其作用是创建一个空的类对象 作为一个类对象 必须具备是三个组成部分 所以调用type中的new来完成组装 得到这个类对象后需要将其返回 以供init来使用

"""

猜你喜欢

转载自www.cnblogs.com/wang-kai-1994/p/10167241.html