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","",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","",1000)
print(p1.__dict__)
类的装饰器应用
Python开发——10.面向对象编程进阶的更多相关文章
- Day7 - Python基础7 面向对象编程进阶
Python之路,Day7 - 面向对象编程进阶 本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...
- Python学习--10 面向对象编程
面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 本节对于面向对象的概念不做 ...
- Python开发——9.面向对象编程
一.面向对象设计(Object oriented design) 面向对象设计是将一类具体事物的数据和动作整合到一起的过程,不会要求面向对象语言编程,但如果想要构造具备对象性质和特点的数据类型,需要更 ...
- Python基础7 面向对象编程进阶
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...
- Python开发【面向对象编程】
一.概述 面向过程:根据业务逻辑从上到下,完成代码: 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可: 面向对象:对函数进行分类和封装. 二.面向对象 1.类.对象.方法.实例 ...
- Python基础-week06 面向对象编程进阶
一.反射 1.定义:指的是通过字符串来操作类或者对象的属性 2.为什么用反射? 减少冗余代码,提升代码质量. 3.如何用反射? class People: country='China' def __ ...
- 进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶
Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...
- python面向对象编程进阶
python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...
- Python:笔记(3)——面向对象编程
Python:笔记(3)——面向对象编程 类和面向对象编程 1.类的创建 说明:和Java不同的是,我们不需要显示的说明类的字段属性,并且可以在后面动态的添加. 2.构造函数 构造函数的功能毋庸置疑, ...
随机推荐
- webapi+ajax跨域问题及cookie设置
最近小玩了点东西,发现简单的东西总能遇到点问题 1.webapi跨域设置 [EnableCors(origins: "*", headers: "*", met ...
- python中list操作方法
1,创建一个列表 只要把逗号分隔的不同的数据项使用方括号括起来即可.如下所示:复制代码 代码如下:list1 = ['physics', 'chemistry', 1997, 2000];list2 ...
- Django2 SQLite3迁移到MySQL数据库
https://blog.csdn.net/weixin_34257076/article/details/86843658
- java关于get/post请求
package com.study.test; import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu ...
- 《Java从入门到精通》学习总结4
1. 程序运行期间,大部分数据都在内存中进行操作,当程序结束时,这些数据将消失. 如果需要将数据永久保存,可使用文件输入流 / 文件输出流与指定的文件建立连接,将需要的数据永久保存到文件中. File ...
- 好用的.NET控制台测试项目
在工作和学习上,我们经常需要创建项目,引用些其他的库,测试下自己的想法是否正确,需要捕捉一下异常.调用一下异步方法.记录一下log等等,这样的项目都是需要花费时间,为了较少花费的时间,产生了一个这样的 ...
- celery 应用
开启服务 #日志 级别 celery -A write_file worker -l info file name :write_file.pyfrom celery import Celery ce ...
- weex h5开发区别-实践初级篇
html标签 weex中没有标签的概念,html中标签对应于weex中的Components weex 无<span> .<p> ,用<text>替代.但是< ...
- python脚本执行报错整理
people = [ {'name':'alex','age':1000}, {'name':'wuxie','age':100}, {'name':'wangcanghai','age':9000} ...
- swift两种获取相册资源PHAsset的路径的方法(绝对路径)
方法中使用到的phasset就是我们取到的PHAsset对象 方法一: let options = PHVideoRequestOptions() options.version = PHVideoR ...