python3-cookbook笔记:第八章 类与对象
python3-cookbook中每个小节以问题、解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构、函数、类等特性在某类问题上如何更好地使用。这本书对于加深Python3的理解和提升Python编程能力的都有显著帮助,特别是对怎么提高Python程序的性能会有很好的帮助,如果有时间的话强烈建议看一下。
本文为学习笔记,文中的内容只是根据自己的工作需要和平时使用写了书中的部分内容,并且文中的示例代码大多直接贴的原文代码,当然,代码多数都在Python3.6的环境上都验证过了的。不同领域的编程关注点也会有所不同,有兴趣的可以去看全文。
python3-cookbook:https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html
8.4 创建大量对象时节省内存方法
创建大量的对象非常的占内存,可能有上百万的数量,这时候可以考虑使用类的__slots__属性,它会将类的实例当成一个固定大小的数组来表示,而不是字典。
但需要注意的是,我们应该尽量少的使用这个属性,因为这种类在定义之后就不再支持添加新属性了,甚至一些类的普通特性也不支持了,比如继承等特性。
import sys class Date:
__slots__ = ['year', 'month', 'day'] def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day d = Date(1, 2, 3) try:
# 不能直接通过打印sys.getsizeof(d)查看实例d的内存大小,可以通过打印它的__dict__属性来查看
# 如果定义了__slots__属性后,实例就没有__dict__属性了,也就是不能动态添加新属性了
print(sys.getsizeof(d.__dict__))
except Exception as e:
print(e)
8.6 创建可管理的属性
当给某个对象的属性赋值时,你想给它进行一些额外的逻辑处理,比如类型检查或者合法性验证的时候,可以使用property装饰器来定义它。定义property属性时,需要注意它们的方法名(也就是属性名)需要都一样。
如果想要定义一个动态的属性时,相比于使用get/set方法的形式,使用property来定义会让Python代码更加优雅。
property基础用法示例:
class Person:
def __init__(self, first_name):
# 这里的self.first_name不是重复定义,而是在property中就定义了
# 这里是在对self.first_name属性赋值,会触发该属性的setter方法
self.first_name = first_name @property
def first_name(self):
"""getter方法:属性名称为方法名称,并且只有定义了getter方法,才能定义其他的setter等方法"""
return self._first_name # 装饰器的前缀名称必须跟property装饰器修饰的方法名称一样,即属性名称
@first_name.setter
def first_name(self, value):
"""方法名称必须跟property装饰器修饰的方法名称一样,即属性名称"""
if not isinstance(value, str):
raise TypeError('Expected a string!!!')
self._first_name = value @first_name.deleter
def first_name(self):
raise AttributeError("Can't delete attribute!!!") a = Person('Guido')
print(a.first_name) try:
a.first_name = 42
except TypeError as e:
print(e) try:
del a.first_name
except AttributeError as e:
print(e)
Guido
Expected a string!!!
Can't delete attribute!!!
定义动态属性:
import math class Circle:
def __init__(self, radius):
self.radius = radius @property
def area(self):
return math.pi * self.radius ** 2 @property
def diameter(self):
return self.radius * 2 @property
def perimeter(self):
return 2 * math.pi * self.radius
8.11 简化数据结构的初始化
当需要写大量的用作数据结构的类,又不想每个类都定义一个__init__方法时,可以参考以下例子。
import math class Structure1:
# 属性名称列表,在子类中覆盖即可
_fields = [] def __init__(self, *args):
if len(args) != len(self._fields):
raise TypeError('Expected {} arguments'.format(len(self._fields))) # 如果需要添加关键字参数,或者添加不在_fields中的关键字参数,也是用这个原理定义即可
for name, value in zip(self._fields, args):
setattr(self, name, value) # 实例化示例
class Stock(Structure1):
_fields = ['name', 'shares', 'price'] class Point(Structure1):
_fields = ['x', 'y'] class Circle(Structure1):
_fields = ['radius'] def area(self):
return math.pi * self.radius ** 2
8.16 在类中定义多个构造器
类方法classmethod的一个主要用途就是定义多个构造器。
import time class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day @classmethod
def today(cls):
"""此方法就相当于第二个构造器了"""
t = time.localtime()
return cls(t.tm_year, t.tm_mon, t.tm_mday) # 使用默认的__init__方法初始化
a = Date(2012, 12, 21)
# 直接返回一个新的实例
b = Date.today()
8.25 创建缓存实例
类似单例模式,某个对象你只想创建一次,或者想要使用之前创建好的对象,就像logging模块,获取相同名称的logger永远只有一个,这个问题除了使用元类等方式,还可以借助weakref模块。但是需要保证weakref.WeakValueDictionary()缓存中的对象在其他地方还在被使用,没有被删除回收掉。
import weakref class Spam:
def __init__(self, name):
self.name = name # 这个变量也可以放在类定义中,用于保证每次类的实例化都返回的是同一个实例对象
# 但是需要保证缓存中的对象在其他地方还在被使用,没有被删除回收掉
_spam_cache = weakref.WeakValueDictionary() # 当程序中其他地方想要使用某个实例时,传入对应名称即可
def get_spam(name):
if name not in _spam_cache:
s = Spam(name)
_spam_cache[name] = s
else:
s = _spam_cache[name]
return s a = get_spam('foo')
b = get_spam('bar')
c = get_spam('foo')
print(a is b) # False
print(a is c) # True
python3-cookbook笔记:第八章 类与对象的更多相关文章
- python cookbook第三版学习笔记十:类和对象(一)
类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair: def __init__(self,x,y): self.x=x self. ...
- php笔记(二)PHP类和对象之Static静态关键字
PHP类和对象之Static静态关键字 静态属性与方法可以在不实例化类的情况下调用,直接使用类名::方法名的方式进行调用.静态属性不允许对象使用->操作符调用. class Car { pr ...
- [javase学习笔记]-6.2 类与对象的关系
这一节我们来看一下类与对象之间的关系. 我们学习java语言,目的就是用java语言对现实生活中的事物进行描写叙述.那么我们如何来描写叙述呢.这就引出了类,我们在实际实现时,是通过类的形式来体现的. ...
- python cookbook第三版学习笔记十三:类和对象(三)描述器
__get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...
- python cookbook第三版学习笔记十三:类和对象(四)描述器
__get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...
- python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法
在子类中调用父类的方法,可以下面的A.spam(self)的方法. class A(object): def spam(self): print 'A.spam' class ...
- delphi高手突破学习笔记之面向对象类和对象的本质
知识点1:堆和栈 每个应用程序可以获得的内存空间分为两种:堆(heap)和栈(stack). 堆又称为“自由存储区”,其中的内存空间的分配与释放是必须由程序员来控制的.例如,用GetMem函数获取了一 ...
- delphi高手突破学习笔记之面向对象类和对象的本质(有汇编解释 good)
知识点1:堆和栈 每个应用程序可以获得的内存空间分为两种:堆(heap)和栈(stack). 堆又称为“自由存储区”,其中的内存空间的分配与释放是必须由程序员来控制的.例如,用GetMem函数获取了一 ...
- php笔记(七)PHP类于对象之多态
<?php interface ICanEat{ public function eat($food);} class Human implements ICaneat{ public func ...
随机推荐
- [bzoj4567] [loj#2012] [SCOI2016] 背单词
Description \(Lweb\) 面对如山的英语单词,陷入了深深的沉思,「我怎么样才能快点学完,然后去玩三国杀呢?」.这时候睿智的凤老师从远处飘来,他送给了 \(Lweb\) 一本计划册和一大 ...
- [bzoj1297] [洛谷P4159] [SCOI2009] 迷路
Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同 ...
- 常用API_1
API API(Application Programming Interface),应用程序编程接口.Java API是一本程序员的 字典 ,是JDK中提供给 我们使用的类的说明文档.这些类将底层的 ...
- 博客与微信小程序的同步
在此之前,先说说自己最近的打算,才购买了阿里云的服务器,想做一个网站和图床网盘之类的方便自己使用. 考虑到小程序,又打算将自己的博客内容放到小程序中.从零开发实属困难,应该还要一段时间才能完成. 目前 ...
- leetcode腾讯精选练习之螺旋矩阵(八)
螺旋矩阵 题目 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素. 示例 1: 输入: [ [ 1, 2, 3 ], ...
- 龙芯 fedora28 安装指南
版权声明:原创文章,未经博主允许不得转载 关于硬件 龙芯3号的板子安装系统都差不多,我分别在 Lemote A1310 和 Lemote A1901 上都尝试过. 本文主要依据 Lemote A190 ...
- [校内训练19_09_02]C
题意 给出一棵N 个节点的树,树上的每个节点都有一个权值$a_i$. 有Q 次询问,每次在树上选中两个点u, v,考虑所有在简单路径u, v 上(包括u, v)的点构成的集合S. 求$\sum_{w∈ ...
- web自动化环境配置
1.下载chrome浏览器对应版本的驱动 下载地址:https://npm.taobao.org/mirrors/chromedriver 2.下载后将chromedriver放到python安装路径 ...
- 使用c++标准IO库实现txt文本文件的读与写操作
练习c++primer中关于输入输出流的操作. 任务是从固定格式的forreading.txt文档中读取相应的数据,转存到forwriting.txt中去. forreading.txt 格式如下: ...
- ATL的GUI程序设计(1)
from:http://blog.titilima.com/atlgui-1.html 第一章 不能免俗的"Hello, World!" 在这一章里,就像所有的入门级教程一样,我也 ...