Python面向对象-元类

反射实际案例

# 利用面向对象编写系统终端功能
  class WinCmd(object):
      def ls(self):
          print('windows系统正在执行ls命令')
      def dir(self):
          print('windows系统正在执行dir命令')
      def cd(self):
          print('windows系统正在执行cd命令')

  class LinuxCmd(object):
      def ls(self):
          print('Linux系统正在执行ls命令')
      def dir(self):
          print('Linux系统正在执行dir命令')
      def cd(self):
          print('Linux系统正在执行cd命令')

  obj = WinCmd()
  obj1 = LinuxCmd()
  """反射提供了一种不需要考虑代码的前提下 操作数据和功能"""
  def run(obj):
      while True:
          cmd = input('请输入您的指令>>>:')
          if hasattr(obj, cmd):
              func_name = getattr(obj, cmd)
              func_name()
          else:
              print('cmd command not found')   
  run(obj1)
  run(obj)
  # 想执行Windows命令就调obj,想执行Linux命令就调obj1

面向对象的双下方法

'''
    面向对象中的双下方法也有一些人称之为是魔法方法
      有些双下方法不需要刻意调用 到达某个条件会自动触发
      __init__  对象实例化的时候会自动触发
  '''

  1.__str__
  对象被执行打印(print、前端展示)操作的时候自动触发
     该方法必须返回字符串类型的数据
  很多时候用来更加精准的描述对象

  2.__del__
    对象被执行(被动、主动)删除操作之后自动执行

  3.__getattr__
    对象查找不存在名字的时候自动触发

  4.__setattr__
    对象在执行添加属性操作的时候自动触发  >>>  obj.变量名=变量值
   
  5.__call__
    对象被加括号调用的时候自动触发

  6.__enter__
    对象被执行with上下文管理语法开始自动触发 
    	该方法返回什么as后面的变量名就会得到什么
    
  7.__exit__
    对象被执行with上下文管理语法结束之后自动触发

  8.__getattribute__
    只要对象查找名字无论名字是否存在都会执行该方法
      如果类中有__getattribute__方法 那么就不会去执行__getattr__方法

  9.__new__
  	pass

笔试题代码简介

1.让字典具备句点符查找值的功能
    # 1.定义一个类继承字典
  class MyDict(dict):
      def __getattr__(self, item):
          return self.get(item)

      def __setattr__(self, key, value):
          self[key] = value
  '''要区别是名称空间的名字还是数据k:v键值对'''
  obj = MyDict({'name':'jason','age':18})
  # 1.具备句点符取v
   print(obj.name)
   print(obj.age)
  # 2.具备句点符设k:v
   obj['gender'] = 'male'
  obj.pwd = 123  # 给字典名称空间添加名字  不是数据k:v
  print(obj)

  2.补全下列代码 使其运行不报错
  	"""
  	class Context:
  	    pass
  	with Context() as ctx:
  	  ctx.do_something()
  	"""
    class Context:
      def __enter__(self):
          return self
      def __exit__(self, exc_type, exc_val, exc_tb):
          pass
      def do_something(self):
          pass
  	with Context() as ctx:
      ctx.do_something()

元类简介

# 元类
	即产生类的类
 
   print(type(123))
   print(type([12, 33, 44]))
   print(type({'name':'jason','pwd':123}))
   type查看的其实是当前对象所属的类名称
   class MyClass(object):
      pass
   obj = MyClass()
   print(type(obj))
   print(type(MyClass))  # <class 'type'>

   class Student:
      pass
   print(type(Student))  # <class 'type'>

   class Teacher(MyClass):
      pass
   print(type(Teacher))  # <class 'type'>
   '''type就是所有类默认的元类!!!'''

产生类的两种表现形式(本质是一种)

1.class关键字
	class C1(object):
    pass
	print(C1)  # <class '__main__.C1'>
	
  2.type元类
  	type(类名,父类,类的名称空间)
    	res = type('C1', (), {})
  		print(res)  # <class '__main__.C1'>
      
  """
  学习元类的目的
  	元类能够控制类的创建 也就意味着我们可以高度定制类的行为
  		eg:掌握了物品的生产过程 就可以在过程中做任何的额外操作
  		
  	比如:要求类的名字必须首字母大写
  	  思考在哪里编写定制化代码
  		类的产生过程目前还比较懵 	   元类里面的__init__方法
  		对象的产生过程呢             类里面的__init__方法
  		方法:由已知推未知
  """

元类的基本使用

"""元类是不能通过继承的方式直接指定的"""
	需要通过关键字参数的形式修改
  class C1(metaclass=MyTypeClass):
      pass
      
  class MyTypeClass(type):
      def __init__(cls, cls_name, cls_bases, cls_dict):
          # print(cls, cls_name, cls_bases, cls_dict)
          if not cls_name.istitle():
              raise Exception("类名的首字母必须大写 你个SD")
          super().__init__(cls_name, cls_bases, cls_dict)

  class C1(metaclass=MyTypeClass):
      school = '斯坦福'

  class a(metaclass=MyTypeClass):  # 直接报错,首字母不是大写
      school = '斯坦福'

元类进阶操作

1.回想__call__方法
	对象加括号会自动执行产生该对象的类里面的__call__,并且该方法返回什么对象加括号就会得到什么
  推导:类加括号会执行元类的里面的__call__该方法返回什么其实类加括号就会得到什么
  """类里面的__init__方法和元类里面的__call__方法执行的先后顺序"""

  class MyTypeClass(type):
      def __call__(self, *args, **kwargs):
          print('__call__ run')
          super().__call__(*args, **kwargs)
  class MyClass(metaclass=MyTypeClass):
        def __init__(self, name):
            print('__init__ run')
            self.name = name
   obj = MyClass('tony')
    
  # 定制对象的产生过程
  class MyTypeClass(type):
      def __call__(self, *args, **kwargs):
          # print('__call__ run')
          # print(args,kwargs)
          if args:
              raise Exception('必须全部采用关键字参数')
          super().__call__(*args, **kwargs)

  class MyClass(metaclass=MyTypeClass):
       def __init__(self, name):
            print('__init__ run')
            self.name = name

   """强制规定:类在实例化产生对象的时候 对象的独有数据必须采用关键字参数"""
   obj1 = MyClass('tony')
   obj2 = MyClass(name='tony')
  """
  如果你想高度定制类的产生过程
  	那么编写元类里面的__init__方法
  如果你想高度定制对象的产生过程
  	那么编写元类里面的__call__方法
  """

双下new方法

__new__用于产生空对象(类)	骨架
  __init__用于实例化对象(类)	血肉

  """
  注意:并不是所有的地方都可以直接调用__new__ 该方法过于底层
  	如果是在元类的__new__里面 可以直接调用
  	class Meta(type):
            def __new__(cls, *args, **kwargs):
            obj = type.__new__(cls,*args,**kwargs)
            return obj
  	如果是在元类的__call__里面 需要间接调用
  	class Mate(type):
      	  def __call__(self, *args, **kwargs):
             obj = object.__new__(self) # 创建一个空对象
             self.__init__(obj,*args,**kwargs) # 让对象去初始化
             return obj
  """
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lamb!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值