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()
浙公网安备 33010602011771号