反射实际案例、面向对象的双下方法、元类简介、__new__方法
作者:互联网
反射实际案例
# 利用面向对象编写简单的模拟终端功能
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('没有此命令')
# run(obj)
run(obj1)
面向对象的双下方法
部分双下方法不需要刻意调用,到达某个条件会自动触发
__str__
对象被执行打印(print、前端展示)操作的时候自动触发
该方法必须返回字符串类型的数据
如果该方法没有返回值那么直接报错,返回的字符串内是什么就会打印什么
很多时候用来更加精准的描述对象
使用:
class Myclass(object):
def __init__(self,name):
self.name = name
def __str__(self):
print('看看我什么时候触发')
return '111'
obj = Myclass('tuzi')
print(obj)
__del__
对象被执行(被动、主动)删除操作之后自动执行
根据垃圾回收机制,代码运行结束会自动释放内存空间来说,主动执行一般在代码运行结束前最后一步执行
使用:
class Myclass(object):
def __init__(self,name):
self.name = name
def __del__(self):
print('看看我什么时候触发')
# 被动删除时,代码执行顺序
obj = Myclass('tuzi')
print('111')
# 111
# 看看我什么时候触发
# 被动删除时,代码执行顺序
obj = Myclass('tuzi')
del obj
print('111')
# 看看我什么时候触发
# 111
__geattr__
对象查找不存在名字的时候自动触发
对象内如果存在则跳过这个__getattr__方法
不存在则执行
使用:
class Myclass(object):
def __init__(self, name):
self.name = name
"""对象查找不存在名字的时候自动触发"""
def __getattr__(self, item):
# item 就是查找的名字
print('没找到', item)
return self, item # 不写返回值的时候会自动返回None
obj = Myclass('tuzi')
print(obj.age) # 没找到 age
print(obj.name) # tuzi
__setattr__
对象在执行添加属性操作的时候自动触发>>>obj.变量名=变量值
使用:
class Myclass(object):
def __init__(self, name):
self.name = name
def __setattr__(self, key, value):
print('__setattr__方法')
# print(key, value)
# 可以做一些扩展
if key == 'name':
raise Exception('不能写入name属性')
print(key, value)
# 如果想要使用对象调用name属性,则需要重新调用__setattr__
super().__setattr__(key,value)
obj = Myclass('tuzi')
print(obj.name)
__call__
对象被加括号调用的时候自动触发
语法形式:def __call__(self, *args, **kwargs)
对象可以传参进来,() {}
也可以有一个return返回值
使用:
class Myclass(object):
def __init__(self, name):
self.name = name
def __call__(self, *args, **kwargs):
print('call方法',args,kwargs)
return '这是返回值'
obj = Myclass('tuzi')
obj() # tuzi
obj(123,name='tuzi') # call方法 (123,) {'name': 'tuzi'}
print(obj(123))
# call方法 (123,) {}
# 这是返回值
__enter__
与__exit___
对象执行with上下文管理语法开始自动触发
该方法返回什么as后面的变量名就会得到什么
class Myclass(object):
def __init__(self, name):
self.name = name
'''对象被执行with上下文管理语法期间自动触发'''
def __enter__(self):
print('__enter__方法')
'''对象被执行with上下文管理语法期间自动触发'''
def __exit__(self, exc_type, exc_val, exc_tb):
print('__exit__方法')
obj = Myclass('tuzi')
with obj as f: # 对象使用with语法是必须使用__enter__与__exit___
pass
__getattribute__
只要对象查找名字无论名字是否存在都会执行该方法
如果类中有__getattribute__方法,那么就不会去执行__getattr__方法
使用:
class Myclass(object):
def __init__(self, name):
self.name = name
"""对象查找不存在名字的时候自动触发"""
def __getattr__(self, item):
# item 就是查找的名字
print('没找到', item)
return self, item # 不写返回值的时候会自动返回一个None
def __getattribute__(self, item): # 都存在的时候,不管找没找到名字都会执行
print('__getattribute__方法',item)
return self,item
obj = Myclass('tuzi')
print(obj.age)
print(obj.name) # tuzi
双下方法笔试题
让字典具备句点符查找值的功能
class MyDict(dict):
def __getattr__(self, item):
return self.get(item)
def __setattr__(self, key, value):
self[key] = value
'''要区别是名称空间的名字还是数据K:V键值对'''
obj = MyDict({'name':'tuzi','age':18})
# 1.具备句点符取V
print(obj.name) # tuzi
# 2.具备句点符设k:v
obj['gender'] = 'male'
print(obj.gender) # male
# 给字典名称空间添加名字 不是数据K:V
obj.pwd = 123
print(obj) # {'name': 'tuzi', 'age': 18, 'gender': 'male', 'pwd': 123}
补全下列代码 使其运行不报错
"""
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()
# 就是补齐with上下文管理语法
元类简介
'''元类:即产生类的类'''
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'>
产生类的两种表现形式(本质是一种)
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__方法
方法:由已知推未知
'''
元类的基本使用
'''元类不能通过继承的方式直接指定'''
需要通过关键字参数的形式修改
元类使用eg:
# 类名的首字母必须大写
class MyTypeClass(type):
def __init__(self, cls_name, cls_bases, cls_dict):
# print(self,cls_name,cls_bases,cls_dict)
if cls_name.istitle():
raise Exception('类名首字母必须大写')
super().__init__(cls_name, cls_bases, cls_dict)
class C1(metaclass=MyTypeClass):
school = '清华大学'
class a(metaclass=MyTypeClass):
pass
元类进阶操作
# 基于__call__方法引申
'''对象加括号会自动执行产生该对象的类里面的__call__,并且该方法返回什么,对象加括号就会得到什么'''
推导:类加括号会执行元类里面的__call__,该方法返回什么其实加括号就会得到什么
类里面的__init__方法和元类里面的__call__方法执行的先后顺序:先执行类里面的__call__然后才轮到类里面的__init__
class MyTypeClass(type):
def __call__(self, *args, **kwargs):
# 理解先后执行顺序
# print('__call__ run')
if args:
raise Exception('必须全部采用关键字参')
super().__call__(*args, **kwargs)
class Myclass(metaclass=MyTypeClass):
def __init__(self,name):
# 理解先后执行顺序
# print('__init__ run')
self.name = name
# 强制规定:类在实例化产生对象的时候,对象的独有数据必须采用关键字参数
# obj = Myclass('tuzi')
obj = Myclass(name = 'tuzi')
小总结
'''
如果你想高度定制类的产生过程
那么编写元类里面的__init__方法
如果你想高度定制对象的产生过程
那么编写元类里面的__call__方法
'''
__new__
方法
__new__用于产生空对象(类) 骨架
__init__用于实例化对象(类) 血肉
类是如何产生的
在经过__init__方法之前,还要再经历一个__new__方法
class MyTypeClass(type):
def __new__(cls, *args, **kwargs):
print('__new__ run')
return super().__new__(cls, *args, **kwargs)
def __init__(cls, cls_name, cls_bases, cls_dict):
print('__init__ run')
super().__init__(cls_name, cls_bases, cls_dict)
class Myclsss(metaclass=MyTypeClass):
def __init__(self, name):
self.name = name
并不是所有的地方都可以直接调用__new__
该方法过于底层,如果是在元类的__new__里面 可以直接调用
class MyTypeClass(type):
def __call__(self, *args, **kwargs):
# 1.产生一个空对象
obj = object.__new__(self,*args, **kwargs)
# return super().__call__(*args,**kwargs) # 也可以直接返回obj
return obj
class Myclsss(metaclass=MyTypeClass):
def __init__(self, name):
self.name = name
obj = Myclsss('jason')
print(obj)
标签:__,obj,name,self,双下,元类,print,def 来源: https://www.cnblogs.com/zhengkaijian/p/16133307.html