python(多态,封装)
多态:由不同的类实例化得到的对象,调用同一个方法,执行的逻辑不同。
# -*- coding: utf-8 -*- import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class Cat(Animal): #动物的形态之一:猫 def talk(self): print('喵喵喵') class Dog(Animal): #动物的形态之二:狗 def talk(self): print('汪汪汪') class Pig(Animal): #动物的形态之三:猪 def talk(self): print('哼哼哼') #统一的接口 def talk(self): self.talk() #实例化 cat=Cat() dog=Dog() pig=Pig() talk(cat) talk(dog) talk(pig)
如上面不同的动物调用相同的函数,实现了不同的功能。
封装
在python中用双下划线开头的方式将属性隐藏起来。(单下划线是开发者之间默认为内部属性,外部不能使用)
以双下划线开头的属性python会自动重命名。
类的继承具有改变和多态的意义。多态就是类的这两层意义的一个具体的实现机制。
反射
自省也称作反射,这个性质展示了某对象是如何在运行期取得自身信息的。如果传一个对象给你,你可以查出它有什么能力,这是一项强大的特性。
# -*- coding: utf-8 -*- class people: #私有属性 __star='earth' def __init__(self,id,name,age,salary): self.id=id self.name=name self.age=age self.salary=salary def get_id(self): print(self.id) p=people('bob',969,20,10000) #asattr()检测对象是否有某属性,方法 print(hasattr(p,'name')) print(hasattr(p,'get_id')) #getattr()获取对象属性值,方法地址 print(getattr(p,'name')) #setattr()添加,修改对象的属性 setattr(p,'hobby','game') print(p.__dict__) #delattr()删除对象的属性 #del p.hobby delattr(p,'hobby') print(p.__dict__)
反射的意义:如以下不同功能开发者之间,即使某些功能未实现,也不影响其他开发者工作。
-*- coding: utf-8 -*- class FtpClient: 'Ftp客户端功能具体实现' def __init__(self,addr): print('正在连接服务器%s'%addr) self.addr=addr
-*- coding: utf-8 -*-
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'): func_get=getattr(f1,'get') func_get() else: print('不存在此方法')
#包含字符串的模块引用 module_1=__import__('C:/lib') module_1.lib.func()
上面的的这个方法一直定位到顶级模块,下面的方法可以直接到你需要的模块
import importlib m=importlib.import_module('C:/lib')
类的内置attr属性
# -*- coding: utf-8 -*- class foo(): pass #查看类的内置属性 print(dir(foo))
class Foo: x=1 def __init__(self,y): self.y=y def __getattr__(self, item): print('----> from getattr:你找的属性不存在') def __setattr__(self, key, value): print('----> from setattr') # self.key=value #这就无限递归了,你好好想想 # self.__dict__[key]=value #应该使用它 def __delattr__(self, item): print('----> from delattr') # del self.item #无限递归了 self.__dict__.pop(item) #__setattr__添加/修改属性会触发它的执行 f1=Foo(10) print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值 f1.z=3 print(f1.__dict__) #__delattr__删除属性的时候会触发 f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作 del f1.a print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发 f1.xxxxxx 三者的用法演示
二次加工标准类型(包装)
意义:根据我们实际需要改写内置方法与属性。
@property详细用法
# -*- coding: utf-8 -*- class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid def append(self, p_object): ' 派生自己的append:加上类型检查' if not isinstance(p_object,int): raise TypeError('must be int') super().append(p_object) @property def mid(self): '新增自己的属性' index=len(self)//2 return self[index] l=List([1,2,3,4]) print(l) l.append(5) print(l) # l.append('1111111') #报错,必须为int类型 print(l.mid) #其余的方法都继承list的 l.insert(0,-123) print(l) l.clear() print(l)
授权
授权的关键是__getattr__覆盖方法
如下,重写了write,添加了功能
# -*- coding: utf-8 -*- import time class FileHandle: def __init__(self,filename,mode='r',encoding='utf-8'): self.file=open(filename,mode,encoding=encoding) def write(self,line): t=time.strftime('%Y-%m-%d %T') self.file.write('%s %s' %(t,line)) def __getattr__(self, item): return getattr(self.file,item) f1=FileHandle('b.txt','w+') f1.write('你好啊\n') time.sleep(1) f1.write('早上好\n') f1.seek(0) print(f1.read()) f1.seek(1) print(f1.read()) f1.close()