多态与面向对象高级
第1章 多态
1.1 什么是多态?
多态指的是同一种事物多种形态
1.2 为什么要用多态?
用基类创建一套统一的规则,强制子类去遵循(使用抽象类实现),这样便可以
在不用考虑对象具体类型的前提下而直接使用对象下的方法
1.3 如何用多态?
示例:
class Animal: def eat(self): pass def drink(self): pass def run(self): pass def bark(self): pass class Cat(Animal): def jiao(self): print('喵喵喵') class Dog(Animal): def speak(self): print('汪汪汪') class Pig(Animal): def han(self): print('哼哼哼') c=Cat() d=Dog() p=Pig()
多态性:可以在不用考虑对象具体类型的前提下而直接使用对象下的方法
c.eat() d.eat() p.eat() c.drink() d.drink() p.drink() d.bark() p.bark() c.bark() d.speak() c.jiao() p.han() import abc #abstract class class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def eat(self): pass @abc.abstractmethod def drink(self): pass @abc.abstractmethod def run(self): pass @abc.abstractmethod def bark(self): pass
# obj=Animal() # 抽象基类本身不能被实例化
class Cat(Animal): def eat(self): print('cat eat') def drink(self): print('cat drink') def run(self): print('cat run') def bark(self): print('喵喵喵') class Dog(Animal): def eat(self): print('dog eat') def drink(self): print('dog drink') def run(self): print('dog run') def bark(self): print('汪汪汪') class Pig(Animal): def eat(self): print('pig eat') def drink(self): print('pig drink') def run(self): print('pig run') def bark(self): print('哼哼哼') c=Cat() d=Dog() p=Pig() c.bark() d.bark() p.bark() def BARK(animal): animal.bark() BARK(c) BARK(d) BARK(p) s='hello' l=[1,2,3] t=(4,5,6) s.__len__() l.__len__() t.__len__() def LEN(obj): return obj.__len__() print(LEN(s)) print(LEN(l)) print(LEN(t)) print(len(l)) print(len(s)) print(len(t))
1.4 鸭子类型
示例
class Foo: def f1(self): print('from foo.f1') def f2(self): print('from foo.f2') class Bar: def f1(self): print('from bar.f1') def f2(self): print('from bar.f2') obj1=Foo() obj2=Bar() obj1.f1() obj1.f2() obj2.f1() obj2.f2() class Disk: def read(self): print('disk read') def write(self): print('disk write') class Txt: def read(self): print('txt read') def write(self): print('txt write') class Process: def read(self): print('process read') def write(self): print('process write') obj1=Disk() obj2=Txt() obj3=Process() obj1.read() obj2.read() obj3.read()
第2章 classmethod与staticmethod
2.1 绑定方法
在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法
绑定对象的方法特殊之处:
应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入
2.2 classmethod
import settings ##先创建一个文件 class People: def __init__(self,name,age): self.name=name self.age=age def tell(self): print('%s:%s' %(self.name,self.age)) @classmethod def from_conf(cls): return cls(settings.NAME,settings.AGE) p=People('egon',19) p.tell() p1=People(settings.NAME,settings.AGE) p1.tell() p2=People(settings.Name,settings.AGE) p3=People('alex',74) p3.tell() print(People.from_conf) p4=People.from_conf(People) print(People.from_conf) p4=People.from_conf() p4.tell()
2.3 staticmethod:非绑定方法,就是一个普通函数
特性:既不跟类绑定,也不跟对象绑定,这意味着谁都能用
谁来用都是一个普通函数,也就是说没有自动传值的特性
import settings import hashlib import time class People: def __init__(self,name,age): self.uid=self.create_id() self.name=name self.age=age def tell(self): print('%s: %s:%s' %(self.uid,self.name,self.age)) @classmethod def from_conf(cls): return cls(settings.NAME,settings.AGE) @staticmethod def create_id(): m=hashlib.md5() m.update(str(time.clock()).encode('utf-8')) return m.hexdigest() obj=People('egon',18) # print(obj.uid,obj.name,obj.age) # obj.tell() # print(obj.create_id) # print(People.create_id) print(obj.create_id()) print(People.create_id())
2.4 内置函数补充(isinstance, issubclass)
示例:
class Foo: pass obj=Foo() print(isinstance(obj,Foo)) # 推荐使用该函数来判断一个函数的类型 print(type(obj) is Foo) print(isinstance('abc',str)) print(isinstance(123,int)) print(issubclass(Foo,object)) #使用该函数来判断一个是不是一个对象
第3章 反射
#下述四个函数是专门用来操作类与对象属性的,如何操作?
#通过字符串来操作类与对象的属性,这种操作称为反射
class People: country="China" def __init__(self,name): self.name=name def tell(self): print('%s is aaa' %self.name) obj=People('egon')
3.1 hasattr
hasattr() 函数用于判断对象是否包含对应的属性。
print(hasattr(People,'country')) print('country' in People.__dict__) print(hasattr(obj,'name')) print(hasattr(obj,'country')) print(hasattr(obj,'tell'))
3.2 getattr
getattr() 函数用于返回一个对象属性值。
x=getattr(People,'country1',None) print(x) f=getattr(obj,'tell',None)#obj.tell print(f == obj.tell) f() obj.tell()
3.3 setattr
setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在
People.x=111 setattr(People,'x',111) print(People.x) obj.age=18 setattr(obj,"age",18) print(obj.__dict__)
3.4 delattr
delattr 函数用于删除属性。
del People.country delattr(People,"country") print(People.__dict__) del obj.name delattr(obj,"name") print(obj.__dict__)
3.5 练习
class Foo: def run(self): while True: cmd=input('cmd>>: ').strip() # print('%s run...' %cmd) if hasattr(self,cmd): func=getattr(self,cmd) func() def download(self): print('download....') def upload(self): print('upload...') obj=Foo() obj.run()
第4章 __str__和__del__方法
示例
__str__ class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __str__(self): # print('========>') return '<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex) obj=People('egon',18,'male') print(obj) #print(obj.__str__()) # l=list([1,2,3]) # print(l)
示例:
__del__ 模仿关闭系统资源 import time class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __del__(self): # 在对象被删除的条件下,自动执行 print('__del__') obj=People('egon',18,'male') del obj #obj.__del__() time.sleep(5)
示例:
class Mysql: def __init__(self,ip,port): self.ip=ip self.port=port self.conn=connect(ip,port) # 申请系统资源 def __del__(self): self.conn.close() obj=Mysql('1.1.1.1',3306) class MyOpen: def __init__(self,filepath,mode="r",encoding="utf-8"): self.filepath=filepath self.mode=mode self.encoding=encoding self.fobj=open(filepath,mode=mode,encoding=encoding) def __str__(self): msg=""" filepath:%s mode:%s encoding:%s """ %(self.filepath,self.mode,self.encoding) return msg def __del__(self): self.fobj.close() # f=open('a.txt',mode='r',encoding='utf-8') f=MyOpen('aaa.py',mode='r',encoding='utf-8') # print(f.filepath,f.mode,f.encoding) # print(f) # print(f.fobj) res=f.fobj.read() print(res)
第5章 元类
示例:
code=""" global x x=0 y=2 """ global_dic={'x':100000} local_dic={} exec(code,global_dic,local_dic) print(global_dic) print(local_dic) code=""" x=1 y=2 def f1(self,a,b): pass """ local_dic={} exec(code,{},local_dic) print(local_dic)
5.1 一切皆对对象
Chinese=type(...) class Chinese: country="China" def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def speak(self): print('%s speak Chinese' %self.name) print(Chinese) p=Chinese('egon',18,'male') print(type(p)) print(type(Chinese)) 元类:类的类就是元类, 我们用class定义的类使用来产生我们自己的对象的 内置元类type是用来专门产生class定义的类的 class Foo: #Foo=type(...) pass print(type(Foo)) f=Foo l=[Foo,] print(l)
5.2 用内置的元类type,来实例化得到我们的类
class_name='Chinese' class_bases=(object,) class_body=""" country="China" def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def speak(self): print('%s speak Chinese' %self.name) """ class_dic={} exec(class_body,{},class_dic)
5.3 类的三大要素
print(class_name,class_bases,class_dic) Chinese=type(class_name,class_bases,class_dic) print(Chinese) p=Chinese('egon',18,'male') print(p.name,p.age,p.sex)
5.4 储备知识__call__
class Foo: def __init__(self): pass def __str__(self): return '123123' def __del__(self): pass
# 调用对象,则会自动触发对象下的绑定方法__call__的执行,
# 然后将对象本身当作第一个参数传给self,将调用对象时括号内的值
#传给*args与**kwargs
def __call__(self, *args, **kwargs): print('__call__',args,kwargs) obj=Foo() # print(obj) obj(1,2,3,a=1,b=2,c=3) #
5.5 自定义元类
class Mymeta(type): # 来控制类Foo的创建 def __init__(self,class_name,class_bases,class_dic): #self=Foo # print(class_name) # print(class_bases) # print(class_dic) if not class_name.istitle(): raise TypeError('类名的首字母必须大写傻叉') if not class_dic.get('__doc__'): raise TypeError('类中必须写好文档注释,大傻叉') super(Mymeta,self).__init__(class_name,class_bases,class_dic) # 控制类Foo的调用过程,即控制实例化Foo的过程 def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={} # print(self) # print(args) # print(kwargs) #1 造一个空对象obj obj=object.__new__(self) #2、调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__ self.__init__(obj,*args,**kwargs) return obj #Foo=Mymeta('Foo',(object,),class_dic) class Foo(object,metaclass=Mymeta): """ 文档注释 """ x=1 def __init__(self,y): self.Y=y def f1(self): print('from f1') obj=Foo(1111) #Foo.__call__() # print(obj) # print(obj.y) # print(obj.f1) # print(obj.x)
5.6 单例模式
import settings class MySQL: __instance=None def __init__(self,ip,port): self.ip=ip self.port=port @classmethod def singleton(cls): if not cls.__instance: obj=cls(settings.IP, settings.PORT) cls.__instance=obj return cls.__instance obj1=MySQL('1.1.1.2',3306) obj2=MySQL('1.1.1.3',3307) obj3=MySQL('1.1.1.4',3308) # obj4=MySQL(settings.IP,settings.PORT) # print(obj4.ip,obj4.port) obj4=MySQL.singleton() obj5=MySQL.singleton() obj6=MySQL.singleton() print(obj4 is obj5 is obj6)