ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

反射实际案例、面向对象的双下方法、元类简介、__new__方法

2022-04-12 01:33:55  阅读:165  来源: 互联网

标签:__ obj name self 双下 元类 print def


燕子不要离开我

反射实际案例

# 利用面向对象编写简单的模拟终端功能
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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有