反射案例及面向对象的双下方法
本章内容
- 反射实际案例
- 面向对象的双下方法
- 元类
- 元类进阶
反射实际案例
利用面向对象编写系统终端功能,代码体现如下:
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)
面向对象的双下方法
面向对象中的双下方法也被有人称之为魔法方法
有些双下方法不需要刻意去调用 因为达到某个条件就会自动触发这个双下方法 例如:
__init__ # 双下init方法在对象实例化的时候自动触发
以下是常见的几种面向对象中的双下方法
1. __ str __
对象被执行时候打印(print,前端展示)操作的时候自动触发
该方法必须返回字符串类型的数据
很多时候用来更加精确的描述对象
2. __ del __
对象被执行(主动、被动)删除操作之后自动执行
3. __ getattr __
对象找不存在名字的时候自动触发
注意:由于没有name,所以在对象查找名字的时候会自动触发双下getattr方法
4. __ setattr __
对象在执行添加属性的操作的时候会自动触发>>> 示例如下:
5. __ call __
对象被加括号调用的时候自动触发

6. __ enter __
对象被执行with上下文管理语法开始自动触发
该方法返回什么as后面的变量名就会得到什么
8. __ getattribute __
只要对象查找名字无论名字是否存在都会执行该方法
如果类中有__ getattribute __ 方法 那么就不会执行 __ getattr __ 方法
笔试题讲解
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)
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))
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 = '清华大学'

元类进阶操作
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')
定制对象的产生过程
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

浙公网安备 33010602011771号