python 面向对象基础和高级复习
面向对象基础
面向对象编程
面向过程编程:类似于工厂的流水线
- 优点:逻辑清晰
- 缺点:扩展性差
面向对象编程:核心是对象二字,对象属性和方法的集合体,面向对象编程就是一堆对象交互
- 优点:扩展性强
- 缺点:逻辑非常复杂
类与对象
对象:属性和方法的集合体
类:一系列相同属性和方法的集合体
现实世界中先有对象后有类,python中先有类,再实例化出对象
对象的属性的查找顺序
先对象本身-->类-->父类-->父类的父类-->object-->自己定制的元类-->type
给对象定制独有属性
class people: pass p1 = peolple() p1.name = 'nick' p2 = people() p2.name = 'tank'
对象的绑定方法
class people: def eat(self): print(self, 'eat....') p1 = peolple() p1.eat() p1.name = 'nick' p2 = people() p2.eat() p2.name = 'tank'
类与数据类型
lis = [1,2,3] # lis = list([1,2,3]) class foo: def __init__(self,name): self.name = name f = foo('name') lis.append(4) # 对象调对象绑定的方法,会自动传参 list.append(lis,4) # 类调用对象绑定的方法,必须得传参
面向对象进阶
类的继承
继承父类,则会有父类的所有属性和方法
class parentclass1(): pass class parentclass2(): pass class subclass(parentclass1,parentclass2): pass
类的派生
继承父类的同时自己有init,然后也需要父类的init
class parentclass1(): def __init__(self,name): pass class subclass(parentclass): def __init__(self,age): # 1. parentclass1.__init__(self,name) # 2. super(subclass,self).__init__(name) self.age = age
gll 加: 派生2中
1.不继承,指明道姓访问一个类的函数
2.严格按继承属性查找关系
super()会得到一个特殊的对象,该对象就是专门用来访问父类中属性的(按照继承的关系)
super().__init__(不用为self传值)
super的完整用法是super(自己的类名,self) ,在python2中需要书写完整,在python3中可以简化为super()
类的组合
类对象可以引用/当做参数传入/当做返回值/当做容器元素,类似于函数对象
class parentclass1(): count = 0 def __init__(self,name): pass class subclass(parentclass): def __init__(self,age): self.age = age pc = parentclass1() sc = subclass() sc.parent_class = pc # 组合 给对象赋予了属性,属性值为对象 pc.count sc.parent_class.count # 0
菱形继承问题
新式类:继承object的类,python3中全是新式类
经典类:没有继承object的类,只有python2中有
在菱形继承的时候,新式类是广度优先(老祖宗最后找);经典类深度优先(一路找到底,再找旁边的)
多态与多态性
一种事物的多种形态,动物-->人/猪/狗
# 多态 import abc class animal(metaclass=abc.abcmeta): @abc.abstractmethod def eat(): print('eat') class people(animal): def eat(): pass class pig(animal): def eat(): pass def run(): pass class dog(animal): # 报错 def run(): pass # 多态性 peo = people() peo.eat() peo1 = people() peo1.eat() pig = pig() pig.eat() def func(obj): obj.eat() class cat(animal): def eat(): pass cat = cat()
鸭子类型:只要长得像鸭子,叫的像鸭子,游泳像鸭子,就是鸭子.
类的封装
隐藏属性,只有类内部可以访问,类外部不可以访问
class foo(): __count = 0 def get_count(self): return self.__count f = foo() f.__count # 报错 f._foo__count # 不能这样做 实在想用就用 _类名__属性,函数同理
类的property特性
定义时,在实例方法的基础上添加 @property 装饰器;并且仅有一个self参数
调用时,无需括号
class people(): def __init__(self,height,weight): self.height = height self.weight = weight @property def bmi(self): return weight/(height**2) @bmi.setter def bmi(self,value) print('setter') @bmi.deleter def bmi(self): print('delter') peo = people peo.bmi
类与对象的绑定方法和非绑定方法
没有任何装饰器装饰的方法就是对象的绑定方法, 类能调用, 但是必须得传参给self
被 @classmethod 装饰器装饰的方法是类的绑定方法,参数写成cls, cls是类本身, 对象也能调用, 参数cls还是类本身
被 @staticmethod 装饰器装饰的方法就是非绑定方法, 就是一个普通的函数
面向对象高级
isinstance,issubclass
isinstance判断是否为类的实例化对象,会检测父类,而type不会检测父类
issubclass,判断是否为其子类
反射
hasattr:通过字符串判断是否类属性存在
getattr:通过字符串获取类属性
setattr:通过字符串修改类属性
delattr:通过字符串删除类属性
gll添加:
应用场景:如何通过sys和getattr获取模块
import time , sys, os mod = sys.modules['__main__'] # 获取的是当前导入的所有模块对应的总内存地址 print(mod) tim = getattr(mod, 'time', none) path = getattr(mod, 'os', none) print(tim.time()) print(path.path)
call
class foo: def __init__(self): print('foo()会触发我') def __call__(self): print('foo()()/f()会触发我') f = foo() f()
new
class foo: def __new__(self): print('new') obj = object.__new__(self) return obj def __init__(self): print('init') f = foo()
元类
元类用来造类的
元类()-->类-->init
元类()()-->对象--->call
类分为几部分:类名/类体名称空间/父类们
class mymeta(type): def __init__(self,class_name,class_bases,class_dic): # 控制类的逻辑代码 super().__init__(class_name,class_bases,class_dic) def __call__(self,*args,**kwargs): # 控制类实例化的参数 obj = self.__new__(self) # obj就是实例化的对象 self.__init__(obj,*args,**kwargs) print(obj.__dict__) # 控制类实例化的逻辑 return obj class people(metaclass=mymeta): def __init__(self,name,age): self.name = name self.age = age
单例模式
利用类的绑定方法的特性
name = 'nick' age = 18 class people(): __instance = none @classmethod def from_conf(cls): if cls.__instance: return cls.__instance cls.__instance = cls(name,age) return cls.__instance
people.from_conf()
people.from_conf()
利用装饰器
name = 'nick' age = 18 def deco(cls): cls.__instance = cls(name,age) def wrapper(*args,**kwargs): if len(args) == 0 and len(kwargs) == 0: return cls.__instance res = cls(*args,**kwargs) return res return wrapper @deco class people(): def __init__(self,name,age): self.name = name self.age = age
peo1 = people()
peo2 = people()
利用元类(正宗的)
name = 'nick' age = 18 class mymeta(type): def __init__(self,class_name,class_bases,class_dict): super().__init__(class_name,class_bases,class_dict) self.__instance = self(name,age) def __call__(self,*args,**kwargs): if len(args) == 0 and len(kwargs) == 0: return self.__instance obj = object.__new__(self) self.__init__(obj,*args,**kwargs) return obj class people(metaclass=mymeta): def __init__(self,name,age): self.name = name self.age = age peo1 = people() peo2 = people()
异常处理
捕捉异常
x = 10 y = 20 c = 30 try: 1/0 except exception as e: print(e)
raise
抛出异常
raise keyboardinterrupt('中断捕捉')
assert
判断某一行代码是否有问题
上一篇: 点击放大图片预览