翻译:《实用的Python编程》04_03_Special_methods
目录 | 上一节 (4.2 继承) | 下一节 (4.4 异常)
4.3 特殊方法
可以通过特殊方法(或者称为"魔术"方法(magic method))自定义 Python 行为的各部分。本节介绍特殊方法的思想。此外,还将讨论动态属性访问和绑定方法。
简介
类可以定义特殊方法。特殊方法对于 Python 解释器而言具有特殊的意义。特殊方法总是以双下划线 __
开头和结尾,例如 __init__
。
class Stock(object):
def __init__(self):
...
def __repr__(self):
...
虽然有很多特殊方法,但是我们只研究几个具体的例子。
字符串转换的特殊方法
对象有两种字符串表示形式。
>>> from datetime import date
>>> d = date(2012, 12, 21)
>>> print(d)
2012-12-21
>>> d
datetime.date(2012, 12, 21)
>>>
str()
函数用于创建格式良好的、可打印的输出:
>>> str(d)
'2012-12-21'
>>>
repr()
函数用于创建详细的、面向程序员的输出。
>>> repr(d)
'datetime.date(2012, 12, 21)'
>>>
str()
和 repr()
函数都是使用类中定义的特殊方法生成要显示的字符串。
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
# Used with `str()`
def __str__(self):
return f'{self.year}-{self.month}-{self.day}'
# Used with `repr()`
def __repr__(self):
return f'Date({self.year},{self.month},{self.day})'
注意:按照惯例,__repr__()
返回一个字符串,当该字符串被传递给 eval()
函数,将会重新创建底层对象(译注:eval(repr(obj)) == obj
)。如果不行,则使用某种易于阅读的表现形式。
数学操作的特殊方法
数学运算符涉及的特殊方法如下:
a + b a.__add__(b)
a - b a.__sub__(b)
a * b a.__mul__(b)
a / b a.__truediv__(b)
a // b a.__floordiv__(b)
a % b a.__mod__(b)
a << b a.__lshift__(b)
a >> b a.__rshift__(b)
a & b a.__and__(b)
a | b a.__or__(b)
a ^ b a.__xor__(b)
a ** b a.__pow__(b)
-a a.__neg__()
~a a.__invert__()
abs(a) a.__abs__()
元素访问的特殊方法
这些是实现容器的特殊方法:
len(x) x.__len__()
x[a] x.__getitem__(a)
x[a] = v x.__setitem__(a,v)
del x[a] x.__delitem__(a)
你可以在类中使用这些特殊方法。
class Sequence:
def __len__(self):
...
def __getitem__(self,a):
...
def __setitem__(self,a,v):
...
def __delitem__(self,a):
...
方法调用
调用方法有两个步骤。
1、查找:.
运算符
2、方法调用: ()
运算符
>>> s = Stock('GOOG',100,490.10)
>>> c = s.cost # Lookup
>>> c
<bound method Stock.cost of <Stock object at 0x590d0>>
>>> c() # Method call
49010.0
>>>
绑定方法
尚未被函数调用运算符 ()
调用的方法称为绑定方法( 译注:bound method,如果直译应该译作“绑定的方法”,但是,就像“类方法”一样,可以省略“的”这个字,译为“绑定方法”,绑定在这里不是动词,而应理解为形容词“绑定的”)。它对自己生成的实例进行操作:
>>> s = Stock('GOOG', 100, 490.10)
>>> s
<Stock object at 0x590d0>
>>> c = s.cost
>>> c
<bound method Stock.cost of <Stock object at 0x590d0>>
>>> c()
49010.0
>>>
如果使用绑定方法时有些大意,那么容易导致错误。示例:
>>> s = Stock('GOOG', 100, 490.10)
>>> print('Cost : %0.2f' % s.cost)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: float argument required
>>>
或者:
f = open(filename, 'w')
...
f.close # Oops, Didn't do anything at all. `f` still open.
在这两种情形中,错误都是由忘记尾部括号引起的。例如:s.cost()
or f.close()
。
属性访问
还有一种访问、操作和管理属性的替代方法。
getattr(obj, 'name') # Same as obj.name
setattr(obj, 'name', value) # Same as obj.name = value
delattr(obj, 'name') # Same as del obj.name
hasattr(obj, 'name') # Tests if attribute exists
示例:
if hasattr(obj, 'x'):
x = getattr(obj, 'x'):
else:
x = None
注意: getattr()
函数的默认参数非常有用。
x = getattr(obj, 'x', None)
练习
练习 4.9:更好的输出
请修改 stock.py
文件中定义的 Stock
对象,以便 __repr__()
方法生成更有用的输出。示例:
>>> goog = Stock('GOOG', 100, 490.1)
>>> goog
Stock('GOOG', 100, 490.1)
>>>
修改完成后,请查看读取股票投资组合时会发生什么,以及生成什么样的结果。示例:
>>> import report
>>> portfolio = report.read_portfolio('Data/portfolio.csv')
>>> portfolio
... see what the output is ...
>>>
练习 4.10:使用 getattr() 的例子
getattr()
是读取属性的另一种机制。可以使用它编写极其灵活的代码。首先,请尝试以下示例:
>>> import stock
>>> s = stock.Stock('GOOG', 100, 490.1)
>>> columns = ['name', 'shares']
>>> for colname in columns:
print(colname, '=', getattr(s, colname))
name = GOOG
shares = 100
>>>
仔细观察会发现输出数据完全由 columns
变量中列出的属性名决定。
在 tableformat.py
文件中,使用该思想将其扩展为通用函数 print_table()
,print_table()
打印一个表格,显示用户指定的任意对象的属性。与早期的 print_report()
函数一样,print_table()
方法还应接受一个 TableFormatter
实例来控制输出格式。它们的工作方式如下:
>>> import report
>>> portfolio = report.read_portfolio('Data/portfolio.csv')
>>> from tableformat import create_formatter, print_table
>>> formatter = create_formatter('txt')
>>> print_table(portfolio, ['name','shares'], formatter)
name shares
---------- ----------
AA 100
IBM 50
CAT 150
MSFT 200
GE 95
MSFT 50
IBM 100
>>> print_table(portfolio, ['name','shares','price'], formatter)
name shares price
---------- ---------- ----------
AA 100 32.2
IBM 50 91.1
CAT 150 83.44
MSFT 200 51.23
GE 95 40.37
MSFT 50 65.1
IBM 100 70.44
>>>
目录 | 上一节 (4.2 继承) | 下一节 (4.4 异常)
注:完整翻译见 https://github.com/codists/practical-python-zh
翻译:《实用的Python编程》04_03_Special_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) 面向对象编程是一种将代码组织成对象集合的编程 ...
随机推荐
- 【转】REST风格框架实战:从MVC到前后端分离(附完整Demo)
版权声明:欢迎转载,注明作者和出处就好!如果不喜欢或文章存在明显的谬误,请留言说明原因再踩哦,谢谢,我也可以知道原因,不断进步! https://blog.csdn.net/justloveyou_/ ...
- SSH服务连接
SSH基本概述 SSH是一个安全协议,在进行数据传输时,会对数据包进行加密处理,加密后在进行数据传输.确保了数据传输安全. SSH服务 ssh: secure shell, protocol, 22/ ...
- Linux-字符处理命令
目录 1.sort(排序) 2.uniq(不相邻的两行重复不会去除) 3.cut(取列,截取字段) 4.wc(统计行.单词.字符数) 1.sort(排序) 选项: -t # 指定分隔符 -k # 指定 ...
- ++i和i++的区别
它们两个的数值变化的区别,我这里就不多说了 这里主要说明两者在效率上的区别 (1)首先如果是自带的数据类型,比如int型,++i和i++,编译器的实现方式是相同的,两者并没有效率上的区别,虽然也有副本 ...
- 桶排序 && leetcode 41
桶排序 对于0-1000 ,用1001个桶 简单版 或者用10个桶0-9,先按各位装桶,然后依(桶)次放回,然后再按十位放桶,放回,然后百位. 也就是基数排序 https://www.cnblogs ...
- npm/yarn查看当前使用源与设置其它源
npm, yarn查看源和换源: npm config get registry // 查看npm当前镜像源 npm config set registry https://registry.npmj ...
- 【DP】区间DP入门
在开始之前我要感谢y总,是他精彩的讲解才让我对区间DP有较深的认识. 简介 一般是线性结构上的对区间进行求解最值,计数的动态规划.大致思路是枚举断点,然后对断点两边求取最优解,然后进行合并从而得解. ...
- HHVM的全称是"HipHop for PHP",开放源代码。采用PHP许可证授权!
http://hhvm.com/ https://github.com/xgqfrms/hhvm 什么是HHVM高性能服务器? HHVM是由Facebook公司出品的高性能开源服务器,用来执行hack ...
- 使用 js 实现十大排序算法: 计数排序
使用 js 实现十大排序算法: 计数排序 计数排序 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- html 布局,上下各100px,中间自适应
flex <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...