面向对象-4
面向对象-4
目录
-
反射实战案例
-
面向对象的魔法方法
-
魔法方法实战演练
-
元类
-
创建类的两种方式
-
元类的实际应用
-
元类——双下new方法
反射实战案例
-
加载配置文件纯大写的配置
import settings new_dict = {} # print(dir(settings)) # dir获取括号中对象可以调用的名字 # ['AGE', 'INFO', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'desc', 'name'] for i in dir(settings): if i.isupper(): # 如果名字是纯大写 那么获取该大写名字对应的值 'AGE' 'INFO' v = getattr(settings, i) new_dict[i] = v print(new_dict)
-
模拟操作系统CMD终端执行用户命令
class WinCmd(object): def dir(self): print('dir获取当前目录下所有的文件名称') def ls(self): print('ls获取当前路径下所有的文件名称') def ipconfig(self): print('ipconfig获取当前计算机的网卡信息') obj = WinCmd() while True: cmd = input('请输入您的命令>>>:') if hasattr(obj, cmd): cmd_name = getattr(obj, cmd) cmd_name() else: print('%s 不是内部或外部命令,也不是可运行的程序或批处理文件' % cmd)
面向对象的魔法方法
-
什么是魔法方法
魔法方法其实就是类中定义的双下方法
这些方法都是到达某个条件自动触发 无需调用 故被称之为魔法方法
-
魔法方法和其触发条件
魔法方法 触发条件 __ init__ (self, name) 给对象设置独有数据的时候自动触发(实例化)
__ str__ (self)对象被执行打印操作的时候会自动触发
该方法必须返回一个字符串
返回什么字符串打印对象之后就展示什么字符串__ call__ (self, *args, **kwargs) 对象加括号调用 自动触发该方法
__ getattr__(self, item)当对象获取一个不存在的属性名 自动触发
该方法返回什么 对象获取不存在的属性名就会得到什么
形参item就是对象想要获取的不存在的属性名__ getattribute__(self, item) 对象获取属性的时候自动触发 (无论这个属性存不存在)
当类中既有__ getattr__ 又有__ getattribute__的时候 只会走后者__ setattr__(self, key, value) 对象操作属性值的时候自动触发>>>: 对象.属性名=属性值 __ del__(self) 对象在被删除(主动 被动)的时候自动触发 __ enter__(self) 对象被with语法执行的时候自动触发
该方法返回什么 as关键字后面的变量名就能得到什么__ exit__(self, exc_type, exc_val, exc_tb) 对象被with语法执行并运行完with子代码之后 自动触发 -
具体触发情况
-
__ init__ (self, name)方法
class MyClass(object): def __init__(self, name): """实例化对象的时候自动触发""" # print('__init__方法') # pass self.name = name
-
__ str__ (self)
class MyClass(object): def __str__(self): """ 对象被执行打印操作的时候会自动触发 该方法必须返回一个字符串 返回什么字符串打印对象之后就展示什么字符串 """ # print('__str__方法') # print('这是类:%s 产生的一个对象') # return '对象:%s'%self return '对象:%s'%self.name
-
__ call__ (self, *args, **kwargs)
class MyClass(object): def __call__(self, *args, **kwargs): """对象加括号调用 自动触发该方法""" print('__call__方法') print(args) print(kwargs)
-
__ getattr__(self, item)
class MyClass(object): def __getattr__(self, item): """当对象获取一个不存在的属性名 自动触发 该方法返回什么 对象获取不存在的属性名就会得到什么 形参item就是对象想要获取的不存在的属性名 """ print('__getattr__', item) return '您想要获取的属性名:%s不存在'%item
-
__ getattribute__(self, item)
class MyClass(object): """对象获取属性的时候自动触发 无论这个属性存不存在 当类中既有__getattr__又有__getattribute__的时候 只会走后者 """ # print('__getattribute__') # return super(MyClass, self).__getattribute__(item) 复杂写法 return super().__getattribute__(item) # 简便写法
-
setattr(self, key, value)
class MyClass(object): def __setattr__(self, key, value): """对象操作属性值的时候自动触发>>>: 对象.属性名=属性值""" # print("__setattr__") # print(key) # print(value) super().__setattr__(key, value)
-
del(self)
class MyClass(object): def __del__(self): """对象在被删除(主动 被动)的时候自动触发""" # print('__del__') pass
-
__ enter__(self)
class MyClass(object): def __enter__(self): """对象被with语法执行的时候自动触发 该方法返回什么 as关键字后面的变量名就能得到什么""" print('__enter__')
-
__ exit__(self, exc_type, exc_val, exc_tb)
class MyClass(object): def __exit__(self, exc_type, exc_val, exc_tb): """对象被with语法执行并运行完with子代码之后 自动触发""" print('__exit__')
元类
-
元类的简介
-
元类前瞻
在接触面向对象之前我们认为所使用的type来查看数据的数据类型
学过面向对象之后,type查看的并不是数据类型,而是数据所属的类
-
数据类型的本质
数据类型的本质 还是通过各个类产生了对象
也可以理解为type用于查看产生当前对象的类是谁
-
元类是如何产生
class MyClass: pass obj = MyClass() print(type(obj)) # 查看产生对象obj的类:<class '__main__.MyClass'> print(type(MyClass)) # 查看产生对象MyClass的类:<class 'type'>
自定义的类都是由type类产生的 , 我们将产生类的类称之为 '元类'
-
-
产生类的两种方式
-
使用class关键字
class MyClass: pass
-
利用元类type
type(类名,类的父类,类的名称空间)
学习元类其实就是掌握了类的产生过程 我们就可以在类的产生过程中高度定制化类的行为
eg:
类名必须首字母大写
上述需求就需要使用元类来控制类的产生过程 在过程中校验
-
-
元类基本使用
class MyMetaClass(type): pass """只有继承了type的类才可以称之为是元类""" class MyClass(metaclass=MyMetaClass): pass """如果想要切换产生类的元类不能使用继承 必须使用关键字metaclass声明""" ''' 思考 类中的__init__用于实例化对象 元类中__init__用于实例化类 ''' class MyMetaClass(type): def __init__(self,what, bases=None, dict=None): # print('别晕') # print('what', what) 类名 # print('bases', bases) 类的父类 # print('dict', dict) 类的名称空间 if not what.istitle(): # print('首字母必须大写 你会不会写python 面向对象学过吗 lowB') raise Exception('首字母必须大写 你会不会写python 面向对象学过吗 lowB') super().__init__(what, bases, dict) """只有继承了type的类才可以称之为是元类""" # class Myclass(metaclass=MyMetaClass): # pass """如果想要切换产生类的元类不能使用继承 必须使用关键字metaclass声明""" class aaa(metaclass=MyMetaClass): pass
-
元类进阶
元类不单单可以控制类的产生过程 其实也可以控制对象的
-
对象加括号执行产生该对象类中的双下call
class MyMetaClass(type): def __call__(self, *args, **kwargs): print('__call__') if args: raise Exception('必须用关键字参数传参') super().__call__(*args, **kwargs)
-
类加括号执行产生该类的元类中的双下call
class MyClass(metaclass=MyMetaClass): def __init__(self, name, age): self.name = name self.age = age print('__init__')
-
实例化对象 所有的参数都必须采用关键字参数的形式
eg : obj = MyClass(name='jason', age=18)
-
总结:
如果我们想高度定制对象的产生过程
可以操作元类里面的__ call__
如果我们想高度定制类的产生过程
可以操作元类里面的__ init__
-
-
双下new方法
类产生对象的步骤
1.产生一个空对象
2.自动触发__ init__方法实例化对象
3.返回实例化好的对象__ new__ 方法专门用于产生空对象
__ init__ 方法专门用于给对象添加属性
-