今日内容
反射实战案例
案例一、
加载配置文件纯大写的配置
import settings
new_dict = {}
for i in dir(settings):
if i.isupper():
v = getattr(settings,i)
new_dict[i] = v
print(new_dict) # 打印结果{'BASE_PATH': '热爱学习', 'NAME': 'joker'}
settings内的数据
BASE_PATH = '热爱学习'
NAME = 'joker'
log = 'log.log'
案例二、
模拟操作系统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('请输入你要指令>>>:').strip()
if hasattr(obj,cmd):
cmd_name = getattr(obj,cmd)
cmd_name()
else:
print('%s 不是内部指令或外部指令,也不是可运行的程序或批处理的文件'%cmd)
"""
请输入你要指令>>>:dir
dir获取当前目录下的所有文件名称
请输入你要指令>>>:ls
ls获取当前路劲下的所有文件名称
请输入你要指令>>>:ipconfig
ipconfig获取当前计算机的网卡信息
请输入你要指令>>>:xxx
xxx 不是内部指令或外部指令,也不是可运行的程序或批处理的文件
"""
面向对象魔法方法
魔法方法其实就是类中定义的双下方法
之所以会叫魔法方法原因是这些方法都是到达某个条件自动触发 无需调用
方法 | 触发条件 |
---|---|
__init__ | 实例化对象的时候自动触发 |
__str__ | 对象被执行打印操作的时候会自动触发 该方法必须返回一个字符串 返回什么字符串打印对象就展示什么字符串 |
__call__ | 对象加括号调用 就会自动触发该方法 |
__getattr__ | 对象获取一个不存在的属性名 自动触发,该方法返回什么 对象获取不存在 对象获取不存在的属性名就会得到什么 |
__setattr__ | 对象操作属性值的时候自动触发>>>:对象.属性名 = 属性值 |
__del__ | 对象在被删除(主动 被动)的时候自动触发 |
__getattribute__ | 对象获取属性的时候自动触发 无论这个属性存不存在 当类中既有__getattr__y又有__getattribute__的时候只会走后者 |
__enter__ | 对象被with语法执行的时候自动触发 该方法返回什么 as关键字后面的变量名就能得到什么 |
__exit__ | 对象被with语法执行并运行完with语法代码后 自动触发 |
__init__
实例化对象的时候自动触发
class MyClass(object):
def __init__(self,):
print('__init__方法')
m1 = MyClass() # __init__方法
__str__
对象被执行打印操作的时候会自动触发 该方法必须返回一个字符串 返回什么字符串打印对象就展示什么字符串
class MyClass(object):
def __init__(self):
print('__init__方法')
def __str__(self):
print('__str__')
return '我必须得是字符串'
m1 = MyClass()
print(m1)
__call__
对象加括号调用 就会自动触发该方法
class MyClass(object):
def __call__(self, *args, **kwargs):
print('__call__方法')
print(args) # ()
print(kwargs) # {}
m1 = MyClass()
m1()
__getattr__
对象获取一个不存在的属性名 自动触发,该方法返回什么 对象获取不存在 对象获取不存在的属性名就会得到什么
class MyClass(object):
def __getattr__(self, item):
print('__getattr__方法')
print(item)
return 'getattr'
m1 = MyClass()
print(m1.name)
__setattr__
对象操作属性值的时候自动触发>>>:对象.属性名 = 属性值
class MyClass(object):
def __init__(self,name):
self.name = name
def __setattr__(self, key, value):
print('__setattr__方法')
print(key) # name
print(value) # joker
m1 = MyClass('joker')
__del__
对象在被删除(主动 被动)的时候自动触发
class MyClass(object):
def __del__(self):
print('__del__方法')
m1 = MyClass()
del m1
__getattribute__
对象获取属性的时候自动触发 无论这个属性存不存在
class MyClass(object):
def __getattribute__(self, item):
print('__getattribute__方法')
m1 = MyClass()
m1.name
__getattr__ 与 __getattribute__
对象获取属性的时候自动触发 无论这个属性存不存在 当类中既有__getattr__又有__getattribute__的时候只会走后者
class MyClass(object):
def __getattr__(self, item):
print('__getattr__方法')
print(item)
return 'getattr'
def __getattribute__(self, item):
print('__getattribute__方法')
m1 = MyClass()
m1.name
__enter__ 与 __exit__
class MyClass(object):
def __enter__(self):
print('__enter__方法')
return 'from enter'
def __exit__(self, exc_type, exc_val, exc_tb):
print('__exit__方法')
m1 = MyClass()
with m1 as f:
print(f)
魔法方法笔试题
"""补全以下代码 执行之后不报错"""
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 f:
f.do_something()
元类简介
基础阶段我们使用type来查找数据的数据类型
但是学了面向对象之后 发现查看的不是数据类型 而是数据所属的类
s1 = '今天不在状态!!!'
l2 = [11, 22, 33, 44]
d = {'name': 'joker', 'age': 18}
print(type(s1)) # <class 'str'>
print(type(l2)) # <class 'list'>
print(type(d)) # <class 'dict'>
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(类名,类的父类,类的名称空间)
type('MyClass',(),{})
学习元类其实就是掌握类的产生过程 我们就可以在类的产生过程中高度定制化类的行为
元类基本使用
class MyMetaClass(type):
def __init__(self,what,bases=None,dict=None):
# print('我好晕')
if not what.istitle():
raise Exception('首字母必须大写 你会不会写python 面向对象没学过吗')
super().__init__(what,bases,dict)
class Myclass(metaclass=MyMetaClass):
pass
class myclass(metaclass=MyMetaClass): # 首字母没有大写会抛异常
pass
元类进阶
class MyMetaClass(type):
def __call__(self, *args, **kwargs):
# print('call')
if args:
raise Exception('必须使用关键字参数传参')
super().__call__(*args,**kwargs)
class Myclass(metaclass=MyMetaClass):
def __init__(self,name,age):
self.name = name
self.age = age
# print('init')
obj = Myclass('jason',18) # 不使用关键字会抛出异常
obj = Myclass(name='jason',age='18')
双下new方法
"""
类产生对象的步骤
1.产生一个空对象
2.自动触发__init__方法实例化对象
3.返回实例化好的对象
"""
__new__方法专门用于产生空对象 骨架
__init__方法专门用于给对象添加属性 血肉