Python基础之面向对象进阶
一、isinstance(obj, cls) & issubclass(sub, super)
isinstance(obj, cls)
检查是否obj是否是类 cls 的对象
1
2
3
4
5
6
|
class Foo( object ): pass obj = Foo() isinstance (obj, Foo) |
issubclass(sub, super)
检查sub类是否是 super 类的派生类
1
2
3
4
5
6
7
|
class Foo( object ): pass class Bar(Foo): pass issubclass (Bar, Foo) |
二、反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
# commons.py 文件 name = "nick" def f1(): return "This is f1." def f2(): return "This is f2." def nb(): return "This is niubily." # index.py 文件 import commons #根据字符串的形式去某个模块中寻找东西 target_func = getattr(commons,"f1") # 找函数 result = target_func() print(result) target_func = getattr(commons,"name") # 找全局变量 print(target_func) target_func = getattr(commons,"age",None) # 找不到返回None print(target_func) #根据字符串的形式去某个模块中判断东西是否存在 tarhas_func = hasattr(commons,"f5") # 找函数 print("before:",tarhas_func) # tarhas_func = hasattr(commons,"name") # 找全局变量 # print(tarhas_func) #根据字符串的形式去某个模块中设置东西 setattr(commons,"f5","lambda x: return \"This is new func.\"") # 设置一个函数 setattr(commons,"age",18) # 设置全局变量 tarhas_func = hasattr(commons,"f5") # 检查函数是否存在 print("after:",tarhas_func) #根据字符串的形式去某个模块中删除东西 delattr(commons,"f5") # 删除一个函数 tarhas_func = hasattr(commons,"f5") # 检查函数是否存在 print("end:",tarhas_func)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 通过字符串的形式,导入模块。起个别名 ccas。 comm = input("Please:") ccas = __import__(comm) ccas.f1() # 需要做拼接导入时后加 fromlist=True(否则只导入lib) ccas = __import__("lib."+comm, fromlist=True)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
##### 路由系统 ##### # 输入 模块名/函数名 (例如:commons/nb) url = input("Please input you want url:") target_module, target_func = url.split("/") #m = __import__("lib."+target_module,fromlist=True) m = __import__(target_module) if hasattr(m,target_func): target_func = getattr(m,target_func) result = target_func() print(result) else: print("Sorry,it's 404 not found.") 路由系统
三、类装饰器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def deco(func): print('===================') return func #fuc=test @deco #test=deco(test) def test(): print('test函数运行') test()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def deco(obj): print('============',obj) obj.x=1 #增加属性 obj.y=2 obj.z=3 return obj @deco #Foo=deco(Foo) #@deco语法糖的基本原理 class Foo: pass print(Foo.__dict__) #加到类的属性字典中 输出 ============ <class '__main__.Foo'> {'__module__': '__main__', 'z': 3, 'x': 1, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, 'y': 2}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def Typed(**kwargs): def deco(obj): for key,val in kwargs.items(): setattr(obj,key,val) return obj return deco @Typed(x=1,y=2,z=3) #typed(x=1,y=2,z=3)--->deco class Foo: pass print(Foo.__dict__) @Typed(name='egon') class Bar: pass print(Bar.name) 控制台输出 {'y': 2, '__dict__': <attribute '__dict__' of 'Foo' objects>, 'z': 3, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__module__': '__main__', 'x': 1, '__doc__': None} egon 增强版
四、元类
ython中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)
寻找类的父亲
#type函数可以查看类型,也可以用来查看对象的类,二者是一样的 print(type(f1)) # 输出:<class '__main__.Foo'> 表示,obj 对象由Foo类创建 print(type(Foo)) # 输出:<type 'type'>
- 元类是类的类,是类的模板
- 元类是用来控制如何创建类的,正如类是创建对象的模板一样
- 元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例,Foo类是 type 类的一个实例)
- type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象
一个类没有声明自己的元类,默认它的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类(顺便我们也可以瞅一瞅元类如何控制类的创建,工作流程是什么)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Mytype(type): def __init__(self,a,b,c): print(self) print(a) print(b) print(c) def __call__(self, *args, **kwargs): print("call") class Slamdunk(metaclass=Mytype): # Mytype("Slamdunk",(object,),{}) 实际上就是这么做,但是传了4个参数 # 声明Foo类由Mytype创建,声明自己的元类 def __init__(self,name): self.name = name s1 = Slamdunk("樱木花道") # 根据python一切皆对象,Slamdunk() 本质上就是在触发创建 Slamdunk类的 元类的__call__ 控制台输出 <class '__main__.Slamdunk'> # 元类创建的实例(对象) Slamdunk # 实例名 () # 继承的类,在python3中都默认继承object,即都为新式类 {'__qualname__': 'Slamdunk', '__init__': <function Slamdunk.__init__ at 0x000002106AFBF840>, '__module__': '__main__'} # 实例类的属性字典 call # 实例+() 触发了元类的__call__方法 模拟初步认识
class Mytype(type): def __init__(self,a,b,c): print(self) def __call__(self, *args, **kwargs): # 传的值是怎么传进去的,就去怎么接收 print("call") obj = object.__new__(self) # 生成一个实例 self.__init__(obj,*args,**kwargs) # 这里的self是Mytype产生的实例,这一步触发 Slamdunk 的构造方法 return obj # __call__方法下的返回值是 self 产生的实例 赋值给s1 class Slamdunk(metaclass=Mytype): # Slamdunk = Mytype("Slamdunk",(object,),{}) 实际上就是这么做,但是传了4个参数 # 声明Foo类由Mytype创建,声明自己的元类 # 触发元类的__init__(元类的构造方法) def __init__(self,name): self.name = name s1 = Slamdunk("樱木花道") # 根据python一切皆对象,Slamdunk() 本质上就是在触发创建 Slamdunk类的 元类的__call__ print(s1.__dict__) # 可以访问到实例对象的属性字典
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Mytype(type): def __init__(self,a,b,c): print(self) def __call__(self, *args, **kwargs): obj = object.__new__(self) self.__init__(obj,*args,**kwargs) return obj class Slamdunk(metaclass=Mytype): def __init__(self,name): self.name = name s1 = Slamdunk("樱木花道") print(s1.__dict__) 控制台输出 <class '__main__.Slamdunk'> {'name': '樱木花道'} # 可以加断点体验 实现创建类的流程 精简版
五、单例模式
单例模式存在的目的是保证当前内存中仅存在单个实例
(程序如果并发量大的话,内存里就会存在非常多功能上一模一样的对象。存在这些对象肯定会消耗内存,对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用)
初级:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 单例模式 class Foo: __n = None def __init__(self): self.name = "nick" self.age = 18 self.job = "pythoner" @staticmethod def dl(): if Foo.__n: return Foo.__n else: Foo.__n = Foo() return Foo.__n # 创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.dl() 。 f1 = Foo.dl() print(f1) f2 =Foo.dl() print(f2) f3 =Foo.dl() print(f3) # 运行结果 <__main__.Foo object at 0x0000000001142390> <__main__.Foo object at 0x0000000001142390> <__main__.Foo object at 0x0000000001142390>
装饰器方式单例模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 装饰器方式单例模式 def singleton(argv): dic = {} def s(*args, **kwargs): if argv not in dic: dic[argv] = argv(*args, **kwargs) return dic[argv] else: return dic[argv] return s # 类上加单例装饰器 @singleton class Foo: pass @singleton class Foo2: pass
升级:
from abc import abstractmethod, ABCMeta class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance class MyClass(Singleton): def __init__(self, name=None): if name: self.name = name a = MyClass("a") print(a) print(a.name) b = MyClass('b') # print(b) print(b.name) # print(a) print(a.name)