反射案例及面向对象的双下方法

本章内容

  • 反射实际案例
  • 面向对象的双下方法
  • 元类
  • 元类进阶

反射实际案例

利用面向对象编写系统终端功能,代码体现如下:

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('请输入您的指令>>>>>>:').strip()
        if hasattr(obj,cmd):
            func_name = getattr(obj,cmd)
            func_name()
        else:
            print('cmd command not found')
run(obj)
image-20220411162739568

面向对象的双下方法

面向对象中的双下方法也被有人称之为魔法方法

有些双下方法不需要刻意去调用 因为达到某个条件就会自动触发这个双下方法 例如:

__init__     # 双下init方法在对象实例化的时候自动触发

以下是常见的几种面向对象中的双下方法

1. __ str __

对象被执行时候打印(print,前端展示)操作的时候自动触发

该方法必须返回字符串类型的数据

很多时候用来更加精确的描述对象

image-20220411172111695

2. __ del __

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

image-20220411172846697

3. __ getattr __

对象找不存在名字的时候自动触发

image-20220411173214187

注意:由于没有name,所以在对象查找名字的时候会自动触发双下getattr方法

4. __ setattr __

对象在执行添加属性的操作的时候会自动触发>>> 示例如下:

image-20220411173907213

5. __ call __

对象被加括号调用的时候自动触发

image-20220411174137397

6. __ enter __

对象被执行with上下文管理语法开始自动触发

该方法返回什么as后面的变量名就会得到什么

image-20220411174946451

8. __ getattribute __

只要对象查找名字无论名字是否存在都会执行该方法

如果类中有__ getattribute __ 方法 那么就不会执行 __ getattr __ 方法

image-20220411181510605

笔试题讲解

1.让字典具备句点符查找值的功能

1.定义一个类继承字典
# 需求:
	1.具备句点符取V的功能
    2.具备句点符设K:V的功能
class MyDict(dict):
    def __getattr__(self, item):
        return self.get(item)
    def __setattr__(self, key, value):
        self[key] = value
obj = MyDict({'name':'tony','age':20})
print(obj.name)
obj.genger = 'male'
print(obj)
image-20220411183310452

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()

注意: 其实就是补全双下enter和双下exit方法,enter返回的是ctx

所以就再写一个方法调用即可,让enter返回对象本身

元类

即产生类的类

class Student:
    pass
obj = Student()
print(type(obj))
print(type(Student))
class Teacher:
    pass
print(type(Teacher))
image-20220411190328169

type就是所有类默认的元类

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

1.class关键字

class Student:
    pass
print(Student)  # <class '__main__.Student'>

2.type元类

res = type('Student',(),{})
print(res)  # <class '__main__.Student'>

学习元类的目的

元类能够控制类的创建 也就意味着我们可以高度定制类的行为

eg: 掌握了物品的生产过程 就可以在过程中做任何的额外操作

元类的基本使用

元类是不能通过继承的方式直接指定的

需要通过关键字参数(metaclass)的形式修改

class MyTypeClass(type):
    def __init__(cls,cls_name,cls_bases,cls_dict):
        if not cls_name.istitle():
            raise Exception('类名的首字母必须大写 你个SD')
        super().__init__(cls_name,cls_bases,cls_dict)
class Student(metaclass=MyTypeClass):
    school = '清华大学'
class a(metaclass=MyTypeClass):
    school = '清华大学'

image-20220411195553800

元类进阶操作

1.回想__ call __方法

​ 对象加括号会自动执行产生该对象的类里面的__ call __,并且该方法

返回什么对象加括号就会得到什么

推导:类加括号会执行元类的里面的__ call __该方法返回什么其实类加括号就会得到什么

类里面的__ init __ 方法和元类里面的__ call __ 方法执行的先后顺序如下:

class MyTypeClass(type):
    def __call__(self, *args, **kwargs):
        print('执行__call__ ')
        super().__call__(*args,**kwargs)
class Myclass(metaclass=MyTypeClass):
    def __init__(self,name):
        print('执行了__init__方法')
        self.name = name
obj = Myclass('tony')
image-20220411200744808

定制对象的产生过程

class MyTypeClass(type):
    def __call__(self, *args, **kwargs):
        if args:
            raise Exception('必须全部采用关键字参数')
        super().__call__(*args,**kwargs)
class Student(metaclass=MyTypeClass):
    def __init__(self,name):
        self.name = name
obj = Student(name='jason')

如果你想高度定制类的产生过程
那么编写元类里面的__ 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
查看源图像
posted @ 2022-04-11 21:12  DDYT  阅读(60)  评论(0)    收藏  举报