首页 > 其他分享 >21.面向对象【五】

21.面向对象【五】

时间:2024-05-10 15:36:09浏览次数:29  
标签:__ 21 面向对象 init call print class name

【一】内置方法补充

1)__call__

# __call__:当类()或对象()调用时触发
class Eg:
    def __init__(self):
        print('执行__init__')
    def __call__(self, *args, **kwargs):
        print('执行__call__')
obj = Eg()  # 执行__init__
obj()  # 执行__call__ 
# 校验当前对象是否可被调用
# 类本身是可以被任意调用的
print(callable(Eg))  # True
# 对象本身是不具备直接被调用的功能的,想让对象也能被调用就必须重写 __call__
print(callable(obj))  # True

2)isinstance(obj,cls)

  • 判断当前对象是否是某一个类的类型
class Animal:
    ...
class Dog:
    ...
animal = Animal()
dog = Dog()
# 判断当前对象是否是指定类型的对象
res_animal = isinstance(dog, Animal)
print(res_animal)  # False
res_dog = isinstance(dog, Dog)
print(res_dog)  # True

3)issubclass(sub,super)

  • 校验一个类是否是属于另一个类的子类
class Animal:
    ...
class Dog(Animal):
    ...
class Cat:
    ...
print(issubclass(Dog, Animal))  # True
print(issubclass(Cat, Animal))  # False

【二】元类

1)概念

  • 元类是所有类的基础,包括object
  • 八大基本数据类型、类实例化得到的对象、类本身均是一种对象
  • 类就是type,即元类

2)元类的创建方法

1.直接用关键字创建

class 类名(继承的父类):
	类体代码
class Student:
    def __init__(self, name):
        self.name = name
print(type(Student))
# <class 'type'>
print(Student.__dict__)
# {'__module__': '__main__', '__init__': <function Student.__init__ at 0x000002A1E21C4400>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

2.通过type创建

类名 = type('类名',(父类1,父类2),名称空间字典)
Student = type('Student', (object,), {'name': 'diva'})
print(Student)
# <class '__main__.Student'>
print(type(Student))
# <class 'type'>
print(Student.__dict__)
# {'name': 'diva', '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

3)元类使用

1.优势

  • 元类可以控制类的创建,即我们可以高度定制类的具体行为

2.元类的基本使用

# 创建元类
class MyType(type):
    def __init__(cls, class_name, class_bases, class_name_space):
        # cls 是当前类的本身
        print(f'cls:{cls}')
        # cls:<class '__main__.MyClass'>
        
        # class_name 当前类的类名
        print(f'class_name:{class_name}')
        # class_name:MyClass
        
        # class_bases 当前类的父类
        print(f'class_bases:{class_bases}')
        # class_bases:()
        
        # class_name_space 当前类的名称空间
        print(f'class_name_space:{class_name_space}')  
        # class_name_space:{'__module__': '__main__', '__qualname__': 'MyClass'}
        
        super().__init__(class_name, class_bases, class_name_space)
# 创建一个继承元类的类
# metaclass 指定元类
class MyClass(metaclass=MyType):
    ...

4)元类进阶使用(控制类名首字母大写)

# 控制当前类名必须首字母大写!首字母不大写就报错!
# 【1】创建元类
class MyType(type):
    def __init__(cls, class_name, class_bases, class_name_space):
        super().__init__(class_name, class_bases, class_name_space)
        # istitle : 首字母必须大写其他必须全小写
        if not class_name.istitle():
            raise TypeError(f'{class_name}首字母必须大写!')
# 【2】创建一个继承元类的类
class Eg(metaclass=MyType):
    ...
# 不报错
class eg(metaclass=MyType):
    ...
# 报错

5)元类__call__补充

class MyType(type):
    def __init__(cls, class_name, class_bases, class_name_space):
        print('MyType的__init__')
        super().__init__(class_name, class_bases, class_name_space)
    def __call__(self, *args, **kwargs):
        print('MyType的__call__')
        obj = super().__call__(*args, **kwargs)
        print('***')
        return obj
class Student(metaclass=MyType):
    def __init__(self, name):
        print('MyClass的__init__')
        self.name = name
    def __call__(self, *args, **kwargs):
        print('MyClass的__call__')

# MyType的__init__
st1 = Student('diva')
# MyType的__call__
# MyClass的__init__
# ***
print(st1())
# MyClass的__call__
# None
print(st1.name)
# diva
  • 高度定制 类的产生过程
    • 编写元类里面的__init__
  • 高度定制 对象的产生过程
    • 编写元类里面的__call__

【三】元类结合__new__

__new__ : 产生空对象(类),用来生成骨架
__init__ : 实例化对象(类),骨架添加血和肉

1)类中的__new__

class MyClass(object):
    def __init__(self, name, age):
        print(f"给当前 MyClass 类的对象初始化属性的时候会触发 __init__")
        self.name = name
        self.age = age
    def __call__(self, *args, **kwargs):
        print(f"当前 MyClass 类的对象被调用的时候会触发 __call__")
        return f'当前 MyClass 类 的 __call__ 的返回值 :>>>> {self.name}'
    # 【三】花骨架 有了骨架才能上色
    def __new__(cls, *args, **kwargs):
        print(f"给当前 MyClass 类的对象创建骨架的时候会触发 __new__")
        # 【1】当前类本身
        print(f" MyClass 类 的 __call__ 的 cls :>>>> {cls}")
        # MyClass 类 的 __call__ 的 cls :>>>> <class '__main__.MyClass'>
        # 【2】当前类初始化传的位置参数
        print(f" MyClass 类 的 __call__ 的 args :>>>> {args}")
        # MyClass 类 的 __call__ 的 args :>>>> ('dream',)
        # 【3】当前类初始化传的关键字参数
        print(f" MyClass 类 的 __call__ 的 kwargs :>>>> {kwargs}")
        # MyClass 类 的 __call__ 的 kwargs :>>>> {'age': 18}
        # 【四】调用父类 的 object 的 __new__ 帮我搭建好骨架
        obj = object.__new__(cls)
        # 【1】查看当前返回值发现是一个对象类型
        print(f'obj :>>>> {obj}')
        # obj :>>>> <__main__.MyClass object at 0x000001984B032340>
        # 【2】发现当前对象的民称空间是空的
        print(f'obj.__dict__ :>>>> {obj.__dict__}')
        # obj.__dict__ :>>>> {}
        # 【五】调用自己的 __init__ 方法 初始化属性
        obj.__init__(*args, **kwargs)
        # 【】给自己的名称空间初始化属性
        print(f'obj.__dict__ :>>>> {obj.__dict__}')
        # obj.__dict__ :>>>> {'name': 'dream', 'age': 18}
        return obj
# MyClass 相当于给你一张纸
# 【一】类() 调用 ---> 一定会触发 __init__ 初始化对象的属性 #  __init__  给你人体骨架上个色
# 【二】在调用  __init__  之前要调用 __new__  # __new__ 相当于将你人体的骨架搭建好
m = MyClass('dream', age=18)
# 【六】完成对象属性的初始化
print(m.name)

2)元类中的__new__

class MyType(type):
    def __init__(cls, class_name, class_bases, class_name_space):
        print(f"给当前 MyType 类的对象初始化属性的时候会触发 __init__")
        super().__init__(class_name, class_bases, class_name_space)
    def __call__(self, *args, **kwargs):
        # 得到一个空的对象
        obj = super().__call__(*args, **kwargs)
        return obj
    # 【三】花骨架 有了骨架才能上色
    def __new__(cls, *args, **kwargs):
        print(f"给当前 MyType 类的对象创建骨架的时候会触发 __new__")
        # 【1】当前类本身
        print(f" MyType 类 的 __call__ 的 cls :>>>> {cls}")
        #  MyType 类 的 __call__ 的 cls :>>>> <class '__main__.MyType'>
        # 【2】当前类初始化传的位置参数
        print(f" MyType 类 的 __call__ 的 args :>>>> {args}")
        #  MyType 类 的 __call__ 的 args :>>>> ('MyClass', (), {'__module__': '__main__', '__qualname__': 'MyClass', '__init__': <function MyClass.__init__ at 0x0000016DE31ACAF0>, '__call__': <function MyClass.__call__ at 0x0000016DE31ACB80>})
        # 【3】当前类初始化传的关键字参数
        print(f" MyType 类 的 __call__ 的 kwargs :>>>> {kwargs}")
        # MyType 类 的 __call__ 的 kwargs :>>>> {}
        # 【四】让你的父类帮你大骨架
        obj = type.__new__(cls, *args, **kwargs)
        print(f'obj :>>>> {obj}')
        # obj :>>>> <class '__main__.MyClass'>
        print(f'obj.__dict__ :>>>> {obj.__dict__}')
        # obj.__dict__ :>>>> {'__module__': '__main__', '__init__': <function MyClass.__init__ at 0x0000023A62C2CB80>, '__call__': <function MyClass.__call__ at 0x0000023A62C2CC10>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}
        return obj
class MyClass(metaclass=MyType):
    def __init__(self, name, age):
        print(f"给当前 MyClass 类的对象初始化属性的时候会触发 __init__")
        self.name = name
        self.age = age
    def __call__(self, *args, **kwargs):
        print(f"当前 MyClass 类的对象被调用的时候会触发 __call__")
        return f'当前 MyClass 类 的 __call__ 的返回值 :>>>> {self.name}'
# MyClass 相当于给你一张纸
# 【一】类() 调用 ---> 一定会触发 __init__ 初始化对象的属性 #  __init__  给你人体骨架上个色
# 【二】在调用  __init__  之前要调用 __new__  # __new__ 相当于将你人体的骨架搭建好
m = MyClass('dream', age=18)
# 【六】完成对象属性的初始化
print(m.name)

标签:__,21,面向对象,init,call,print,class,name
From: https://www.cnblogs.com/Mist-/p/18184450

相关文章

  • 洛谷题单指南-动态规划2-P3147 [USACO16OPEN] 262144 P
    原题链接:https://www.luogu.com.cn/problem/P3147题意解读:将一组数据两两相邻且相同的合并,合并成一个数值+1的数,求合并后的最大值。解题思路:考虑合并后的最大数i,其最后一次必然是由两个i-1合并而来的设dp[i][j]表示以j为左端点,合并最大值为i时的右端点的下一个位置如图:dp[i......
  • 2021看雪SDC议题回顾 | SaTC:一种全新的物联网设备漏洞自动化挖掘方法
    https://zhuanlan.zhihu.com/p/431335767随着物联网技术的日新月异,未来物联网的应用将越来越广泛,但它同样也会带来大量安全漏洞。而当下IoT漏洞挖掘技术尚未完全成熟,许多人的信息安全意识不够强,技术革新面临着巨大的安全隐患。来自上海交通大学的陈力波老师所提出的SaTC:一种全新......
  • 面向对象编程(basic)
    面向对象内容的三条主线:Java类及类的成员:(重点)属性、方法、构造器;(熟悉)代码块、内部类面向对象的特征:封装、继承、多态、(抽象)其他关键字的使用:this、super、package、import、static、final、interface、abstract等1.面向对象VS面向过程面向过程思想线性思维步......
  • Python进阶之面向对象编程
    【一】人狗大战小游戏【1】游戏前提分析人可以打狗,狗掉血,狗可以咬人,人掉血人的属性有名字、年龄、伤害、血量、类型狗的属性有名字、年龄、伤害、血量、类型【2】游戏实现(1)定义人和狗的属性#【1】用字典定义,代码较冗余dog1={'name':'狗蛋','d_type':'中......
  • P5214 [SHOI2014] 神奇化合物
    题目链接:https://www.luogu.com.cn/problem/P5214题意:给定一张无向图,分别进行以下操作:Q:询问图中有多少连通块;Auv:代表在uv之间链接一条边;Duv:代表删除链接uv的边。做法:考虑到题目数据范围较小,直接用邻接表存边即可。可以发现有些点是不会进行改变的,可以讲在线询问转成......
  • 力扣刷题笔记-21 合并两个有序链表
    其实不回答就是答案双指针classSolution{publicListNodemergeTwoLists(ListNodelist1,ListNodelist2){ListNodedummy=newListNode(-1);ListNodep=dummy;ListNodep1=list1,p2=list2;while(p1!=null&&p2!=nu......
  • 215. 数组中的第K个最大元素
    给定整数数组nums和整数k,请返回数组中第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。你必须设计并实现时间复杂度为O(n)的算法解决此问题。示例1:输入:[3,2,1,5,6,4],k=2输出:5示例2:输入:[3,2,3,1,2,4,5,5,6......
  • 20211317李卓桐 Exp6 MSF攻防实践 实验报告
    Exp6MSF攻防实践实践内容本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路。具体需要完成:1.1一个主动攻击实践,尽量使用最新的类似漏洞;1.2一个针对浏览器的攻击,尽量使用最新的类似漏洞;1.3一个针对客户端的攻击,如Adobe或office,尽量使用最新的类似......
  • mac80211子系统学习-rx部分
    mac80211子系统学习-rx部分wifi网卡架构Linux将wifi芯片分成了fullmac和softmac两种类型,两种类型的区别在于mlme被driver+hardware实现还是被kernel实现,用wirelesswiki上的话来讲:SoftMACisatermusedtodescribeatypeofWNICwheretheMLMEisexpectedtobema......
  • 20212217刘恒谦-Exp6 MSF攻防实践
    实践内容本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路。具体需要完成:一个主动攻击实践,尽量使用最新的类似漏洞;(1分)首先生成木马文件,通过socat传输到windows主机上:​windows主机接收文件到火绒信任区,避免误杀:​之后,在windows中运行该木马程序,......