Python开发——10.面向对象编程进阶
一、isinstance(obj,cls)和issubclass(sub,super)
1.isinstance(obj,cls)
判断obj是不是由cls产生的类
2.issubclass(sub,super)
判断sub是否是super的子类
3.代码
class Foo:
def __init__(self,name):
self.name = name
class Son(Foo):
# pass
def __init__(self,name):
self.name = name
f1 =Foo("dazui")
f2 = Son("zuizui")
print(isinstance(f1,Foo))#True,判断对象是否由类实例化而来的
print(isinstance(f2,Foo))#True
print(isinstance(f2,Son))#True
print(issubclass(Son,Foo))#True
print(issubclass(Foo,Son))#False
print(type(f1),type(f2))#<class '__main__.Foo'> <class '__main__.Son'>
二、反射
1.定义
通过字符串的形式操作对象相关的属性。
2.四个函数
class Intermedia:
def __init__(self,name,addr):
self.name = name
self.addr = addr
def rent_house(self):
print("%s正在租房子"%(self.name))
i1 = Intermedia("自如","翠屏山")
#hasattr:判断对象是否包含指定的数据属性,也可以判断类是否包含指定的函数属性
print(hasattr(i1,"name"))#True
print(hasattr(Intermedia,"rent_house"))#True
#getattr:传入三个参数,如果数据属性存在,则返回该数据属性的值,不存在则返回指定的内容
print(getattr(i1,"name","自定义的内容"))#i1没有nam22e这个属性,打印“自定义内容”
#setattr:设置数据属性和函数属性
setattr(i1,"price",1600)
print(i1.__dict__)#{'price': 1600, 'name': '自如', 'addr': '翠屏山'}
#删除属性
delattr(i1,"price")
print(i1.__dict__)#{'name': '自如', 'addr': '翠屏山'}
delattr(Intermedia,"rent_house")
3.优点
(1)实现可插拔机制
class FtpClient:
"Ftp客户端,但具体功能还没实现"
def __init__(self,addr):
self.addr = addr
def put(self):
print("正在上传文件")
from ftp_client import FtpClient
f1 = FtpClient("1.1.1.1")
if hasattr(f1,"put"):
func_get = getattr(f1,"put")
func_get()
else:
print("执行其他功能")
(2)动态导入模块
import importlib
module_t = importlib.import_module("m1.test")
print(module_t)#<module 'm1.test' from 'D:\\python_s3\\day27\\m1\\test.py'>
module_t.test1()
module_t._test2()
from m1 import test
test.test1()
test._test2()
module_t = __import__("m1.test")
print(module_t)#<module 'm1' from 'D:\\python_s3\\day27\\m1\\__init__.py'>
module_t.test.test1()
module_t.test._test2()
from m1.test import *
test1()
_test2()#用*的方式导入找不到_test2()
from m1.test import test1,_test2
test1()
_test2()
三、__setattr__、__delattr__和__getattr__
class Foo:
y = 24
def __init__(self,x):
self.x = x
def __getattr__(self, item):
print("执行__getattr__")
def __delattr__(self, item):
print("执行__delattr__")
def __setattr__(self, key, value):
print("执行__setattr__")
self.__dict__[key] = value
f1 = Foo(8)
#__getattr__,当要找的属性不存在时,执行__getattr__
getattr(f1,"不存在")#执行__getattr__
#__delattr__:当实例删除属性时,执行
del f1.y#执行__delattr__
del Foo.y#不执行__delattr__
#设置属性时执行__setattr__
f1 = Foo(8)#执行__setattr__
f1.z = 6#执行__setattr__
四、二次加工标准类型
1.包装
利用继承和派生知识,基于标准的数据类型来定制需求的数据类型,新增或改写方法。包装一个类型通常是对已存在的类型的一些定制,可以新建、修改或删除原有功能,其他保持不变
class List(list):
def append(self, p_object):
if type(p_object)==str:
# list.append(self,p_object)
super().append(p_object)
else:
print("输入的不是字符串类型")
def show_middle(self):
return self[int(len(self)/2)]
l = List("hello world!")
print(l)
l.append(123)#输入的不是字符串类型
2.授权
授权是包装的一个特性,授权的过程是所以更新的功能都由新类的某部分来处理,已存在的功能设为对象的默认属性
import time
class Open:
def __init__(self,filename,mode,encoding="utf-8"):
# self.filename = filename
self.file = open(filename,mode,encoding=encoding)
self.mode = mode
self.encoding = encoding
def write(self,line):
t = time.strftime("%Y-%m-%D %X")
self.file.write("%s %s" %(t,line))
def __getattr__(self, item):
return getattr(self.file,item)
f1 = Open("a.txt","w")
f1.write("111111\n")
f1.write("222222\n")
五、__getattribute__
class Foo:
def __init__(self,name):
self.name = name
def __getattr__(self, item):
print("执行getattr")
def __getattribute__(self, item):#无论能否找到都执行__getattribute__,只有抛出AttributeError时会执行__getattr__ print("执行getattribute")
raise AttributeError("抛出异常")#会去执行__getattr__
# raise TabError("抛出异常")#不会去执行__getattr__
f1 = Foo("大嘴")
f1.age
六、__setitem__、__getitem__和__delitem__
class Foo:
def __init__(self,name):
self.name = name
def __getitem__(self, item):
print("执行__getitem__")
return self.__dict__[item]
def __setitem__(self, key, value):
print("执行__setitem__")
def __delitem__(self, key):
print("执行__delitem__")
f1 = Foo("dazui")
print(f1["name"])#执行__getitem__
f1["age"]=18#执行__setitem__
del f1["name"]#执行__delitem__
七、__str__、__repr__和__format__
1.利用__str__或__repr__改变对象的字符串显示
class Foo:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return "这是str的返回结果 name:%s age: %s" %(self.name,self.age)
def __repr__(self):
return "这是repr的返回结果 name:%s age: %s" %(self.name,self.age)
f1 = Foo("大嘴",80)
print(f1)#<__main__.Foo object at 0x001D5F30>默认显示,\
# 定义__str__时,显示str的返回值;没有__str__,定义了__repr__,显示repr的返回值
2.利用__format__定制格式化字符串
format_dic={
"ymd":"{0.y} {0.m} {0.d}",
"y:m:d":"{0.y}:{0.m}:{0.d}",
"d-m-y":"{0.d}-{0.m}-{0.y}"
}
class Data:
def __init__(self,y,m,d):
self.y = y
self.m = m
self.d = d
def __format__(self, format_spec):
print("执行__format__")
print(format_spec)
if not format_spec or format_spec not in format_dic:
format_spec = "ymd"
fm = format_dic[format_spec]
return fm.format(self)
d1 = Data(2018,5,18)
print(format(d1,"yaaaaaaaaa"))
八、__slots__
# 节省内存,对象不能新建数据属性
class Foo:
__slots__ = ["name","age"]
f1=Foo()
print(Foo.__slots__)
print(f1.__slots__)
f1.name = "dazui"
f1.age = 80
print(f1.name,f1.age)
f1.gender = "female"#'Foo' object has no attribute 'gender'
九、__next__和__iter__实现迭代器协议
1.代码
class Foo:
def __init__(self,x):
self.x = x
def __iter__(self):
return self
def __next__(self):
if self.x == 15:
raise StopIteration("迭代器中止")
self.x += 1
return self.x
f1 = Foo(10)
print(f1.__next__())
print(next(f1))
for i in f1:#从13开始循环
print(i)
2.实现菲波那切数列
class Fib:
def __init__(self,a,b):
self._a = a
self._b = b
def __iter__(self):
return self
def __next__(self):
if self._a>200:
raise StopIteration
self._a,self._b = self._b,self._a+self._b
return self._a
f1 = Fib(1,2)
print(next(f1))
print(f1.__next__)
print("<><><><><><><><><><><><><><><><>")
for i in f1:
print(i)
十、__doc__
#描述信息不会被继承
class Foo:
"Foo的描述信息"
pass
class Son(Foo):
pass
print(Foo.__doc__)#Foo的描述信息
print(Son.__doc__)#None
十一、__module__和__class__
__module__表示当前操作对象在哪个模块
__class__表示当前操作对象的类
from test.test1 import Foo
f1 = Foo("dazui")
print(f1.__module__)#test.test1
print(f1.__class__)#<class 'test.test1.Foo'>
十二、__del__
析构方法,当对象在内存中被释放时,自动触发执行
class Foo:
def __init__(self,name):
self.name = name
def __del__(self):
print("执行析构函数")
f1 = Foo("dazui")#执行析构函数
# del f1.name
# print("<><>")#先打印"<><>",然后执行构析函数释放内存
#<><>
# 执行析构函数
del f1#先执行构析函数释放内存,然后打印"<><>"
print("<><>")
#执行析构函数
# <><>
十三、__call__
#对象后面加(),触发执行
class Foo:
def __call__(self, *args, **kwargs):
print("执行__call__")
f1 = Foo()
f1()#执行__call__
十四、__enter和__exit__
1.with语句
又称上下文管理协议,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
2.优点
(1)使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
(2)在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制。
3.代码
class Foo:
def __init__(self,name):
self.name = name
def __enter__(self):
print("执行__enter__")#出现with语句,执行,返回值赋给as声明的变量
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("执行__exit__")
print(exc_type)#异常类
print(exc_val)#异常值
print(exc_tb)#追踪信息
return True#异常被清空,with后面的语句正常执行,如不返回,会抛出异常,,程序停止执行
with Foo("a.txt") as f :
print(f)
print(大嘴)
print("<><><><><><><><><><><>")
十五、metaclass
元类是类的类,元类创建类正如类创建对象,当一个类没有声明自己的元类,它的默认元类就是type,,除了使用元类type,用户也可通过继承type来自定义元类
1.另一种定义类的方式
def __init__(self,name,age):
self.name = name
self.age = age
def test(self):
print("test")
Foo = type("Foo",(object,),{"x":1,"__init__":__init__,"test":test})
f1 = Foo("dazui",18)
print(f1.name)
f1.test()
2.自定义元类
class MyType(type): def __init__(self,a,b,c): print(self,a,b,c) print("元类的构造函数执行") def __call__(self, *args, **kwargs): print(self,*args,**kwargs) obj = object.__new__(self) self.__init__(obj,*args,**kwargs) return obj class Foo(metaclass=MyType): def __init__(self,name): self.name = name f1 = Foo("alex")
十六、property
一个静态属性property本质就是实现了get、set、delete三种方法
class Goods: def __init__(self): self.original_price = 100 self.discount = 0.8 @property def new_price(self): new_price = self.original_price*self.discount return new_price @new_price.setter def price(self,value): self.original_price = value @new_price.deleter def del_price(self): del self.original_price g1 = Goods() print(g1.new_price) g1.price = 200 print(g1.original_price) del g1.original_price
class Foo: def get_AAA(self): print("get的时候运行") def set_AAA(self,value): print("get的时候运行") def del_AAA(self): print("del的时候运行") AAA = property(get_AAA,set_AAA,del_AAA) f1 = Foo() f1.AAA = "aaa" del f1.AAA
十七、 描述符
1.描述符定义
描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__()和__delete__()中的一个
__get__():调用一个属性时触发
__set__():设置一个属性时触发
__get__():调用一个属性时触发
2.作用
描述符是用来代理另外一个类的属性,必须把描述符定义为这个类的类属性,不能定义到构造函数中
3.分类
(1)数据描述符:至少实现了__get__()和__set__()
(2)非数据描述符:没有实现__set__()
4.优先级
从高到低类属性>s数据描述符>实例属性>非数据描述符>找不到属性触发__getattr__()
5.描述符的应用
class Nametype: def __init__(self,key,expected_type): self.key = key self.expected_type = expected_type def __get__(self, instance, owner): print("__get__方法") return instance.__dict__[self.key] def __set__(self, instance, value): print("__set__方法") if not isinstance(value,self.expected_type): raise TypeError("%s输入类型错误,不是%s" %(self.key,self.expected_type)) instance.__dict__[self.key] =value def __delete__(self, instance): instance.__dict__.pop(self.key) class People: name = Nametype("name",str) age = Nametype("age",int) def __init__(self,name,age,salary): self.name = name self.age = age self.salary = salary p1 = People("dazui","18",19999)
6.类的装饰器
def deco(obj): print(obj) obj.x = 1 obj.y = 2 obj.z = 3 return obj @deco#Foo = deco(Foo) class Foo: pass print(Foo.__dict__)
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) class Foo: pass print(Foo.__dict__) @Typed(name = "dazui") class Bar: pass print(Bar.__dict__)
7.类的装饰器应用
class Nametype: def __init__(self,key,expected_type): self.key = key self.expected_type = expected_type def __get__(self, instance, owner): return instance.__dict__[self.key] def __set__(self, instance, value): if not isinstance(value,self.expected_type): raise TypeError("%s输入类型错误,不是%s" %(self.key,self.expected_type)) instance.__dict__[self.key] =value def __delete__(self, instance): instance.__dict__.pop(self.key) def deco(**kwargs): def wrapper(obj): for key,val in kwargs.items(): setattr(obj,key,Nametype(key,val)) return obj return wrapper @deco(name = str,age = int) class People: def __init__(self,name,age,salary): self.name = name self.age = age self.salary = salary p1 = People("dazui","18",1000) print(p1.__dict__)
posted on 2018-05-21 21:45 hechengwei 阅读(204) 评论(0) 编辑 收藏 举报