翻译:《实用的Python编程》07_05_Decorated_methods
目录 | 上一节 (7.4 装饰器) | 下一节 (8 测试和调试)
7.5 装饰方法
本节讨论一些与方法定义结合使用的内置装饰器。
预定义的装饰器
在类定义中,有许多预定义的装饰器用于指定特殊类型的方法。
class Foo:
def bar(self,a):
...
@staticmethod
def spam(a):
...
@classmethod
def grok(cls,a):
...
@property
def name(self):
...
让我们逐个查看吧。
静态方法
@staticmethod 用于定义所谓的静态类方法( static class method,来自于 C++/Java)。静态方法是一个函数,这个函数是类的一部分,但不是在实例上进行操作。
class Foo(object):
@staticmethod
def bar(x):
print('x =', x)
>>> Foo.bar(2)
x=2
>>>
静态方法有时用于实现类的内部支持代码,例如,用于帮助管理已创建的实例(内存管理,系统资源,持久化,锁等等)。有时也用于某些设计模式(这里暂不讨论)。
类方法
@classmethod 用于定义类方法(class methods)。类方法是一种将 类 对象而不是实例作为第一个参数的方法。
class Foo:
def bar(self):
print(self)
@classmethod
def spam(cls):
print(cls)
>>> f = Foo()
>>> f.bar()
<__main__.Foo object at 0x971690> # The instance `f`
>>> Foo.spam()
<class '__main__.Foo'> # The class `Foo`
>>>
类方法常用作定义替代构造函数(constructor)的工具。
import time
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
# Notice how the class is passed as an argument
tm = time.localtime()
# And used to create a new instance
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
d = Date.today()
类方法可以和继承等特性一起使用以解决棘手的问题。
class Date:
...
@classmethod
def today(cls):
# Gets the correct class (e.g. `NewDate`)
tm = time.localtime()
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
class NewDate(Date):
...
d = NewDate.today()
练习
练习 7.11:实践中的类方法
在 report.py 和 portfolio.py 文件中, Portfolio 类的创建稍微有点混乱。例如,report.py 程序具有如下代码:
def read_portfolio(filename, **opts):
'''
Read a stock portfolio file into a list of dictionaries with keys
name, shares, and price.
'''
with open(filename) as lines:
portdicts = fileparse.parse_csv(lines,
select=['name','shares','price'],
types=[str,int,float],
**opts)
portfolio = [ Stock(**d) for d in portdicts ]
return Portfolio(portfolio)
且 portfolio.py 文件中定义的 Portfolio 具有一个奇怪的初始化:
class Portfolio:
def __init__(self, holdings):
self.holdings = holdings
...
坦白说,因为代码分散在各文件中,所以责任链稍微有点混乱。如果 Portfolio 类应该包含 Stock 类的实例列表,那么你应该修改该类以使其更清晰。示例:
# portfolio.py
import stock
class Portfolio:
def __init__(self):
self.holdings = []
def append(self, holding):
if not isinstance(holding, stock.Stock):
raise TypeError('Expected a Stock instance')
self.holdings.append(holding)
...
如果想要从 CSV 文件中读取投资组合数据,那么你也许应该为此创建一个类方法:
# portfolio.py
import fileparse
import stock
class Portfolio:
def __init__(self):
self.holdings = []
def append(self, holding):
if not isinstance(holding, stock.Stock):
raise TypeError('Expected a Stock instance')
self.holdings.append(holding)
@classmethod
def from_csv(cls, lines, **opts):
self = cls()
portdicts = fileparse.parse_csv(lines,
select=['name','shares','price'],
types=[str,int,float],
**opts)
for d in portdicts:
self.append(stock.Stock(**d))
return self
要使用新的 Portfolio 类,你可以这样编写代码:
>>> from portfolio import Portfolio
>>> with open('Data/portfolio.csv') as lines:
... port = Portfolio.from_csv(lines)
...
>>>
请对 Portfolio 类进行修改,然后修改 report.py 的代码以使用类方法。
目录 | 上一节 (7.4 装饰器) | 下一节 (8 测试和调试)
注:完整翻译见 https://github.com/codists/practical-python-zh
翻译:《实用的Python编程》07_05_Decorated_methods的更多相关文章
- 翻译:《实用的Python编程》InstructorNotes
实用的 Python 编程--讲师说明 作者:戴维·比兹利(David Beazley) 概述 对于如何使用我的课程"实用的 Python 编程"进行教学的问题,本文档提供一些通用 ...
- 翻译:《实用的Python编程》README
欢迎光临 大约 25 年前,当我第一次学习 Python 时,发现 Python 竟然可以被高效地应用到各种混乱的工作项目上,我立即被震惊了.15 年前,我自己也将这种乐趣教授给别人.教学的结果就是本 ...
- 翻译:《实用的Python编程》05_02_Classes_encapsulation
目录 | 上一节 (5.1 再谈字典) | 下一节 (6 生成器) 5.2 类和封装 创建类时,通常会尝试将类的内部细节进行封装.本节介绍 Python 编程中有关封装的习惯用法(包括私有变量和私有属 ...
- 翻译:《实用的Python编程》04_02_Inheritance
目录 | 上一节 (4.1 类) | 下一节 (4.3 特殊方法) 4.2 继承 继承(inheritance)是编写可扩展程序程序的常用手段.本节对继承的思想(idea)进行探讨. 简介 继承用于特 ...
- 翻译:《实用的Python编程》01_02_Hello_world
目录 | 上一节 (1.1 Python) | 下一节 (1.3 数字) 1.2 第一个程序 本节讨论有关如何创建一个程序.运行解释器和调试的基础知识. 运行 Python Python 程序始终在解 ...
- 翻译:《实用的Python编程》03_03_Error_checking
目录 | 上一节 (3.2 深入函数) | 下一节 (3.4 模块) 3.3 错误检查 虽然前面已经介绍了异常,但本节补充一些有关错误检查和异常处理的其它细节. 程序是如何运行失败的 Python 不 ...
- 翻译:《实用的Python编程》03_04_Modules
目录 | 上一节 (3.3 错误检查) | 下一节 (3.5 主模块) 3.4 模块 本节介绍模块的概念以及如何使用跨多个文件的函数. 模块和导入 任何一个 Python 源文件都是一个模块. # f ...
- 翻译:《实用的Python编程》03_05_Main_module
目录 | 上一节 (3.4 模块) | 下一节 (3.6 设计讨论) 3.5 主模块 本节介绍主程序(主模块)的概念 主函数 在许多编程语言中,存在一个主函数或者主方法的概念. // c / c++ ...
- 翻译:《实用的Python编程》04_01_Class
目录 | 上一节 (3.6 设计讨论) | 下一节 (4.2 继承) 4.1 类 本节介绍 class 语句以及创建新对象的方式. 面向对象编程(OOP) 面向对象编程是一种将代码组织成对象集合的编程 ...
随机推荐
- js 动态修改页面文本字体
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Dart: path库
path库pub地址 安装: dependencies: path: 使用: import 'dart:io'; import 'package:path/path.dart' as path; ma ...
- CF102920L Two Buildings【分治】【决策单调性】
优秀的分治题目.是"2020-2021 ACM-ICPC, Asia Seoul Regional Contest"的一道题. Description There are \(n\ ...
- 1004 Counting Leaves ——PAT甲级真题
1004 Counting Leaves A family hierarchy is usually presented by a pedigree tree. Your job is to coun ...
- 扒几个 3D 模型备用
前言 在上一篇中,我展示了 OpenGL 开发的基本过程,算是向 3D 世界迈出的一小步吧.对于简单的 3D 物体,比如立方体.球体.圆环等等,我们只需要简单的计算就可以得到他们的顶点的坐标.但是仅仅 ...
- OAuth2.0安全设计之Authorization Code
OAuth 2.0 有 4 种认证流程: 授权码模式(authorization code) 简化模式(implicit) 密码模式(resource owner password credentia ...
- Django3.0 + nginx + uwsgi 部署
CentOS7.6 下部署Django3.0应用,使用nginx+uwsgi部署: 1. uwsgi部署 pip install uwsgi 在项目的根目录中,新建文件夹 conf, 然后进入conf ...
- 后端程序员之路 41、BlockingQueue
BlockingQueue,阻塞队列,常用于实现生产者和消费者模型特点:1.队列为空时,取操作会等到队列有数据2.队列满时,存操作会等到队列可用 基于C++11的阻塞队列简单实现 - Cynric 的 ...
- CentOS Install NMP
目录 Installation steps of the Nginx install run 默认安装路径 指定安装目录 Installation steps of the MySQL 下载源码包 解 ...
- MySQL 异常有这一篇就够了!
摘要:在本文中,总结了开发过程中最为常见的几种 MySQL 抛出的异常以及如何解决,包括高版本驱动的问题.时区配置问题.SSL 连接问题等,是一篇经验总结贴. 前言 在本文中,总结了开发过程中最为常见 ...