单例模式
类每次实例化的时候都会创建一个新的对象,如果要求类只能被实例化一次该怎么做呢?
class Earth: |
类可以多个实例化
<__main__.Earth object at 0x000001D54B28A978> 2015600617848 |
我们可以看出,多个实例化,每个实例化的地址都不相同。
class Earth: |
类的实例化的时候,会在init前调用new方法。
<__main__.Earth object at 0x0000024EF2DBA940> 2538105186624 |
可以看出两次创建对象,结果返回的是同一个对象实例
变量共享
class Earth: |
输出
<__main__.Earth object at 0x000002077AA33E80> 2231145545344 |
应用
- Python的logger就是一个单例模式,用以日志记录
- Windows的资源管理器是一个单例模式
- 线程池,数据库连接池等资源池一般也用单例模式
- 网站计数器
使用情况
当每个实例都会占用资源,而且实例初始化会影响性能,这个时候就可以考虑使用单例模式,它给我们带来的好处是只有一个实例占用资源,并且只需初始化一次;
当有同步需要的时候,可以通过一个实例来进行同步控制,比如对某个共享文件(如日志文件)的控制,对计数器的同步控制等,这种情况下由于只有一个实例,所以不用担心同步问题。
总结
初始化函数之前:new方法会在初始化函数init方法之前执行。
单例模式:利用这个new方法可以很方便的实现类的单例模式。
合理利用:new 方法合理利用可以带来方便,常应用在类的单例模式。
定制属性访问
如何判断一个实例里面有某个属性呢?
怎样删除实例属性呢?
同样的怎样删除变量呢?
class Rectangle: |
接下来我们来对类的属性进行定制化
增加属性
setattr
setattr(b, 's', 12) |
往类的属性里面添加方法并赋值。
b.__setattr__('s', 5) |
等价于类的对应魔术方法
删除属性
delattr
delattr(b, 's') |
删除属性
b.__delattr__('s') |
等价于类的对应魔术方法
修改属性
setattr
b.s |
同样是使用setattr来修改属性
b.__setattr__('s', 20) |
等价于类的对应魔术方法
查找属性
hasattr
hasattr(b, 's') |
有对应属性就返回True,否则就返回Flase
getattr
getattr(b, 's') |
有就返回属性值,没有就报错。
b.__getattribute__('s') |
扩展
我们在查询属性的时候,使用getattr,如果没有属性值,又不想报错怎么办呢?
class Rectangle: |
getattr(b, 's') |
当属性不存在时,如果定义了此方法,则调用方法等价于类的对应魔术方法
总结
hasattr: 判断是否存在属性,如果属性存在则进行下一步操作。
getattr: 得到属性值。
setattr:设置属性。
描述符
如果在一个类中实例化另一个类,对这个属性进行访问的时候怎么做的?
class MyAtrribute: |
<__main__.MyAtrribute object at 0x000001F4922CF2E8> |
返回的是对象
class MyAtrribute: |
get |
直接访问时,调用get方法
class MyAtrribute: |
<__main__.MyClass object at 0x000002312DAEBF28> |
根据访问时带使用不同的方式,调用不用的属性。
总结
描述符大家了解即可
魔术方法的作用其实是让开发人员能够更加灵活的控制类的表现形式
装饰器
之前我们讲了闭包,闭包中可以传入一个函数吗?
def fx(x): |
12
这是我们前面所见过的闭包
def f1(func): |
<function f1.<locals>.f2 at 0x0000026D2F4BA488> |
闭包传入函数
语法糖
def f1(func): |
f2 running |
在Python中直接用语法糖,f3(3) = f1(f3)(3)
内置装饰器
@property
class Rectangle: |
12 |
访问函数时,就像访问属性一样
@staticmethod
class Rectangle: |
func |
静态方法
@classmethod
class Rectangle: |
<class '__main__.Rectangle'> |
类方法:cls代表类本身,如果加上self,在调用时就要把实例传入。
类装饰器
class Test_Class: |
类 |
类也可以做装饰器,但是需要定义call 方法
扩展
查看函数运行时间的装饰器
import time |
star time: 12/19/18 |
总结
装饰器本质是闭包,在不影响原函数使用的情况下,增加原函数功能。
内置装饰器:三个内置装饰器是需要掌握的,在项目中会经常使用。