一、isinstance和issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类 class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)
二、反射
反射:是用字符串类型的名字,去操作变量
反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力
"""反射:是用字符串类型的名字,去操作变量""" # name = 1 # eval("print(name)") # 1 容易出现安全隐患 # 反射 就没有安全问题 # 反射对象的属性和方法 hasattr getattr setattr delattr class A: price = 200 def func(self): print("in func") a = A() a.name = "alex" a.age = 18 # 反射对象的属性 # ret = getattr(a, "name") # alex 通过变量名的字符串形式取到的值 # print(ret) # alex # # 反射对象的方法 # """里面是字符串,变成函数和对象的内存地址,加个()就可以调用方法""" # ret = getattr(a, "func") # print(ret) # <bound method A.func of <__main__.A object at 0x00000299778143C8>> # ret() # in func # # class A: # price = 200 # # @classmethod # def func(cls): # print("in func") # # # # 反射类的属性 # # A.price # ret = getattr(A, "price") # print(ret) # 200 # # 反射类的方法 classmethod 和staticmethod # # A.func() # if hasattr(A,"func"): # 如果成立我就执行,不会报错 # ret = getattr(A, "func")() # ret() # in func # 反射模块的属性 # print(res) # import my # # # # print(my.girl) # ret = getattr(my, "girl") # print(ret) # # # 反射模块的方法 # my.eva() # if hasattr(my, "eva"): # ret = getattr(my, "eva")() # print(ret) # 内置模块也能用 import time # time.sleep() ret = getattr(time, "sleep") ret(2) import sys year = 2019 print(sys.modules) # '__main__': <module '__main__' print(sys.modules["__main__"].year) def eva(): print("eva我喜欢听你讲课") # 反射自己模块中的变量 getattr(sys.modules["__main__"], "year") # 反射自己模块中的方法 if hasattr(sys.modules["__main__"], "eva"): getattr(sys.modules["__main__"], "eva")() name = input(">>>>>>>>>>:") print(getattr(sys.modules[__name__], "name")) # setattr 设置修改变量,没有就添加 class A: pass a = A() setattr(a, "name", "nezha") setattr(A, "name", "eva") print(a.name) print(A.name) # delattr 删除 delattr(a, "name") delattr(A, "name") # print(a.name)
二、元类
元类:创建类的类
对象是通过类实例化产生的,如果类也是对象的话,必然类对象也是有另一个类实例化产生的(类就是元类的对象)
定义类的规则都是从元类那来的
默认情况下所有类的元类都是type,但是type是继承object
创建类的三个要素;
class Person(object): name =123 pass #1.类名 (字符类型)2.类的父类或基类(元组或列表)3.类的名称空间(字典类型)
1.type是继承object
class Person: pass p = Person() print(type(p)) # <class '__main__.Person'> print(p.__class__) # <class '__main__.Person'> print(type(Person)) # <class 'type'> 元类 type() #<class 'type'>
2.只要继承了type 那么这个类就变成了一个元类
""" 学习元类的目的:高度自定义一个类 只要继承type,这个类就变成了元类 需求:控制类的名字必须以“驼峰式”的方式来书写,否则报错""" # 定义元类 class MyType(type): def __init__(self, clss_name, bases, dict): super().__init__(clss_name, bases, dict) # 类的三要素:类名,基类(父类),类的名称空间 print(clss_name, bases, dict) if not clss_name.istitle(): raise Exception("名字不会写?类名要大写,sb") # 指定元类 class Pig(metaclass=MyType): pass # 通过__init__方法控制类名(类的属性) # MyType("pig", (), {}) 初始化方法
三、__call__方法的应用
1.自定义__call__方法
class MyMeta(type): def __init__(self, name, bases, dict): super().__init__(name, bases, dict) print("你个铺盖仔") def __call__(self, *args, **kwargs): # 可变参数爱传不传 print("元类 call run") print(self) # <class '__main__.Dog'>Dog类 print(args) # ()('大帅',)把对象属性传参传进来了 print(kwargs) # {}字典,传进来 return super().__call__(*args, **kwargs) class Dog(metaclass=MyMeta): # 会走元类init方法 Dog =MyMeta("Dog",(),{}) def __init__(self, name): self.name = name def __call__(self, *args, **kwargs): print("call run") d = Dog("大帅") # 类是元类的对象 print(d.name) # 当你把类实例化会自动触发元类call方法,*args是位置传参列表元祖,*kwargs是字典"""
2.需求把对象属性改为大写
# 创建元类 class MyType(type): def __call__(self, *args, **kwargs): new_args = [] for i in args: new_args.append(i.upper()) # print(new_args) print(kwargs) return super().__call__(*new_args, **kwargs) # 执行或覆盖call方法 class Person(metaclass=MyType): def __init__(self, name, gender): self.name = name self.gender = gender p = Person("wukai", "man") print(p.name, p.gender) # WUKAI ,MAN # 调用自定义元类__call__方法可以修改对象属性 # 注意自定义元类中,重点在于覆盖父类__call__方法,并返回其值
class MyType(type): def __call__(self, *args, **kwargs): if args: raise Exception("顶你的费,不允许,用位置参数传参") # print(new_args) print(kwargs) return super().__call__(*args, **kwargs) # 执行或覆盖call方法 class Person(metaclass=MyType): def __init__(self, name, gender): self.name = name self.gender = gender p = Person(name="wukai",gender="man") p = Person("wukai", "man") print(p.name, p.gender)
四、__new__方法
当你要创建类对象时,会首先执行元类中__new__方法,先新创建“类对象”,然后自动调用__init__方法,对这个类进行初始化
注意:new方法必须有返回值且必须是 对应的对象"
# 自定义元类 class Meta(type): def __new__(cls, *args, **kwargs): print(cls) # 元类自己 print(args) # 创建类需要的几个参数:类名 基类 名称空间 print(kwargs) # 空字典 print("run new") return super().__new__(cls, *args, **kwargs) # 初始化类对象,必须有返回值且是类对象 # obj=type.__new__(cls,*args,**kwargs) # 第二种方法 # return obj def __init__(self, a, b, c): super().__init__(a, b, c) print("run init") class A(metaclass=Meta): pass print(A) # 总结:new方法和init方法都可以实现控制类的创建过程,init更简单些 # a = A()
五、单例模式
设计模式:用于解决某种固定问题的套路
单例:指的是一个类只能产生一个对象
单例目的:单例是为了节省资源,当一个类的所有对象属性全部相同时,则没有必要创建多个对象,浪费资源
单例元类 class Single(type): def __call__(self, *args, **kwargs): if hasattr(self, "obj"): return getattr(self, "obj") obj = super().__call__(*args, **kwargs) # 初始化call方法 print("new 了") self.obj = obj return obj class Student(metaclass=Single): def __init__(self, name, age): self.name = name self.age = age stu = Student("jack", 18) stu = Student("jack", 18) stu = Student("jack", 18)