CS61A:STRING REPRESENTATION

Python 规定所有对象都应该产生两种不同的字符串表示形式:一种是人类可解释的文本,另一种是 Python 可解释的表达式。字符串的构造函数 str 返回一个人类可读的字符串。在可能的情况下,repr 函数会返回一个计算结果相等的 Python 表达式。repr 的文档字符串解释了这个属性:


repr(object) -> stringReturn the canonical string representation of the object.
For most object types, eval(repr(object)) == object.</span></span>

对表达式的值调用 repr 的结果是 Python 在交互式会话中打印的结果。

>>> 12e12
12000000000000.0
>>> print(repr(12e12))
12000000000000.0

如果不存在计算结果为原始值的表示形式,Python 通常会生成一个用尖括号括起来的描述。

>>> repr(min)
'<built-in function min>'
str 构造函数通常与 repr 重合,但在某些情况下提供更易解释的文本表示形式。例如,我们看到 str 和 repr 之间的日期存在差异。
>>> from datetime import date
>>> tues = date(2011, 9, 12)
>>> repr(tues)
'datetime.date(2011, 9, 12)'
>>> str(tues)
'2011-09-12'

repr 函数总是在其参数上调用一个名为 __repr__ 的方法。

>>> tues.__repr__()
'datetime.date(2011, 9, 12)'

str 构造函数的实现方式与此类似:它对其参数调用名为 __str__ 的方法。

>>> tues.__str__()
'2011-09-12'

True 和 false 值。我们之前看到 Python 中的数字有一个真值;更具体地说,0 是 false 值,所有其他数字都是 true 值。事实上,Python 中的所有对象都有一个 truth 值。默认情况下,用户定义类的对象被视为 true,但可以使用特殊的 __bool__ 方法来覆盖此行为。如果对象定义了 __bool__ 方法,则 Python 会调用该方法来确定其真值。


例如,假设我们希望余额为 0 的银行账户为 false。我们可以向 Account 类添加一个 __bool__ 方法来创建此行为。

>>> Account.__bool__ = lambda self: self.balance != 0

我们可以调用 bool 构造函数来查看对象的真值,并且可以在布尔上下文中使用任何对象。
>>> bool(Account('Jack'))
False
>>> if not Account('Jack'):print('Jack has nothing')
Jack has nothing


序列作。我们已经看到,我们可以调用 len 函数来确定序列的长度。

>>> len('Go Bears!')
9


len 函数调用其参数的 __len__ 方法来确定其长度。所有内置序列类型都实现了此方法。

>>> 'Go Bears!'.__len__()
9

__getitem__ 方法由元素选择运算符调用,但也可以直接调用。

>>> 'Go Bears!'[3]
'B'
>>> 'Go Bears!'.__getitem__(3)
'B'

Callable 对象。在 Python 中,函数是一等对象,因此它们可以作为数据传递,并且具有与任何其他对象一样的属性。Python 还允许我们通过包含 __call__ 方法来定义可以像函数一样“调用”的对象。使用此方法,我们可以定义一个行为类似于高阶函数的类。

>>> def make_adder(n):def adder(k):return n + kreturn adder
>>> add_three = make_adder(3)
>>> add_three(4)
7
>>> class Adder(object):def __init__(self, n):self.n = ndef __call__(self, k):return self.n + k
>>> add_three_obj = Adder(3)
>>> add_three_obj(4)
7

复数可以用两种几乎等效的方式表示:矩形形式(实部和虚部)和极坐标形式(大小和角度)。有时矩形形式更合适,有时极性形式更合适。事实上,完全可以想象一个系统,其中复数以两种方式表示,并且用于作复数的函数与任何一种表示形式一起工作。我们在下面实现这样的系统。顺便说一句,我们正在开发一个对复数执行算术运算的系统,作为使用泛型运算的程序的一个简单但不切实际的示例。复数类型实际上内置于 Python 中,但在此示例中,我们将实现自己的类型。

>>> class Number:def __add__(self, other):return self.add(other)def __mul__(self, other):return self.mul(other)
>>> class Complex(Number):def add(self, other):return ComplexRI(self.real + other.real, self.imag + other.imag)def mul(self, other):magnitude = self.magnitude * other.magnitudereturn ComplexMA(magnitude, self.angle + other.angle)
  • ComplexRI constructs a complex number from real and imaginary parts.
    ComplexRI 从实部和虚部构造一个复数。
  • ComplexMA constructs a complex number from a magnitude and angle.
    ComplexMA 从大小和角度构造一个复数。
>>> from math import atan2
>>> class ComplexRI(Complex):def __init__(self, real, imag):self.real = realself.imag = imag@propertydef magnitude(self):return (self.real ** 2 + self.imag ** 2) ** 0.5@propertydef angle(self):return atan2(self.imag, self.real)def __repr__(self):return 'ComplexRI({0:g}, {1:g})'.format(self.real, self.imag)

Python 具有一个简单的功能,用于从零参数函数动态计算属性。@property 修饰器允许在没有 call 表达式语法(表达式后面的括号)的情况下调用函数。ComplexRI 类存储 real 和 imag 属性,并按需计算大小和角度。

同样,ComplexMA 类存储 magnitude 和 angle,但每当查找这些属性时,都会计算 real 和 imag。

>>> from math import sin, cos, pi
>>> class ComplexMA(Complex):def __init__(self, magnitude, angle):self.magnitude = magnitudeself.angle = angle@propertydef real(self):return self.magnitude * cos(self.angle)@propertydef imag(self):return self.magnitude * sin(self.angle)def __repr__(self):return 'ComplexMA({0:g}, {1:g} * pi)'.format(self.magnitude, self.angle/pi)

对幅值或角度的更改会立即反映在 real 和 imag 属性中。

>>> ma = ComplexMA(2, pi/2)
>>> ma.imag
2.0
>>> ma.angle = pi
>>> ma.real
-2.0

泛型函数是适用于不同类型参数的方法或函数。我们已经看到了很多例子。Complex.add 方法是通用的,因为它可以将 ComplexRI 或 ComplexMA 作为 other 的值。这种灵活性是通过确保 ComplexRI 和 ComplexMA 共享一个接口获得的。使用接口和消息传递只是用于实现泛型函数的几种方法之一。在本节中,我们将考虑另外两个:类型调度和类型强制。

假设,除了复数类之外,我们还实现了一个 Rational 类来精确表示分数。add 和 mul 方法表示与本章前面的 add_rational 和 mul_rational 函数相同的计算。

>>> from fractions import gcd
>>> class Rational(Number):def __init__(self, numer, denom):g = gcd(numer, denom)self.numer = numer // gself.denom = denom // gdef __repr__(self):return 'Rational({0}, {1})'.format(self.numer, self.denom)def add(self, other):nx, dx = self.numer, self.denomny, dy = other.numer, other.denomreturn Rational(nx * dy + ny * dx, dx * dy)def mul(self, other):numer = self.numer * other.numerdenom = self.denom * other.denomreturn Rational(numer, denom)
>>> from math import pi
>>> ComplexRI(1, 2) + ComplexMA(2, pi/2)
ComplexRI(1, 4)
>>> ComplexRI(0, 1) * ComplexRI(0, 1)
ComplexMA(1, 1 * pi)
能够直接用运算符进行操作的原因是在number class中,就已经进行了__add__ , __mul__的运算符重载

内置函数 isinstance 接受一个对象和一个类。如果对象具有一个类,则该类是给定类或继承自给定类,则返回 true。

>>> c = ComplexRI(1, 1)
>>> isinstance(c, ComplexRI)
True
>>> isinstance(c, Complex)
True
>>> isinstance(c, ComplexMA)
False

类型调度的一个简单示例是 is_real 函数,该函数对每种类型的复数使用不同的实现。

>>> def is_real(c):"""Return whether c is a real number with no imaginary part."""if isinstance(c, ComplexRI):return c.imag == 0elif isinstance(c, ComplexMA):return c.angle % pi == 0
>>> is_real(ComplexRI(1, 1))
False
>>> is_real(ComplexMA(2, pi))
True

类型调度并不总是使用 isinstance 执行。对于算术,我们将为 Rational 和 Complex 实例提供一个具有字符串值的 type_tag 属性。当两个值 x 和 y 具有相同的type_tag时,我们可以直接用 x.add(y) 将它们组合在一起。如果没有,我们需要一个 cross-type作。

>>> Rational.type_tag = 'rat'
>>> Complex.type_tag = 'com'
>>> Rational(2, 5).type_tag == Rational(1, 2).type_tag
True
>>> ComplexRI(1, 1).type_tag == ComplexMA(2, pi/2).type_tag
True
>>> Rational(2, 5).type_tag == ComplexRI(1, 1).type_tag
False

为了组合复数和有理数,我们编写了同时依赖于它们的两种表示形式的函数。下面,我们依赖于一个事实,即 Rational 可以近似地转换为一个实数的 float 值。结果可以与复数组合。

>>> def add_complex_and_rational(c, r):return ComplexRI(c.real + r.numer/r.denom, c.imag)

乘法涉及类似的转换。在极坐标形式中,复平面中的实数总是具有正大小。角度 0 表示正数。角度 pi 表示负数。

>>> def mul_complex_and_rational(c, r):r_magnitude, r_angle = r.numer/r.denom, 0if r_magnitude < 0:r_magnitude, r_angle = -r_magnitude, pireturn ComplexMA(c.magnitude * r_magnitude, c.angle + r_angle)

加法和乘法都是可交换的,因此交换参数 order 可以使用这些跨类型运算的相同实现。

>>> def add_rational_and_complex(r, c):return add_complex_and_rational(c, r)
>>> def mul_rational_and_complex(r, c):return mul_complex_and_rational(c, r)

我们使用 type_tag 属性来区分参数的类型。也可以直接使用内置的 isinstance 方法,但 tags 简化了实现。使用类型标签还说明了类型调度不一定链接到 Python 对象系统,而是一种在异构域上创建泛型函数的通用技术。


__add__ 方法考虑两种情况。首先,如果两个参数具有相同的 type 标签,则它假定第一个参数的 add 方法可以将第二个参数作为参数。否则,它会检查名为 adders 的跨类型实现字典是否包含可以添加这些类型标签的参数的函数。如果存在这样的函数,cross_apply 方法会查找并应用它。__mul__ 方法具有类似的结构。

>>> class Number:def __add__(self, other):if self.type_tag == other.type_tag:return self.add(other)elif (self.type_tag, other.type_tag) in self.adders:return self.cross_apply(other, self.adders)def __mul__(self, other):if self.type_tag == other.type_tag:return self.mul(other)elif (self.type_tag, other.type_tag) in self.multipliers:return self.cross_apply(other, self.multipliers)def cross_apply(self, other, cross_fns):cross_fn = cross_fns[(self.type_tag, other.type_tag)]return cross_fn(self, other)adders = {("com", "rat"): add_complex_and_rational,("rat", "com"): add_rational_and_complex}multipliers = {("com", "rat"): mul_complex_and_rational,("rat", "com"): mul_rational_and_complex}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/77227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LangChain缓存嵌入技术完全指南:CacheBackedEmbedding原理与实践(附代码示例)

一、嵌入缓存技术背景与应用场景 1.1 为什么需要嵌入缓存&#xff1f; 算力消耗问题&#xff1a;现代嵌入模型&#xff08;如text-embedding-3-small&#xff09;单次推理需要约0.5-1秒/文本 资源浪费现状&#xff1a;实际业务中约30%-60%的文本存在重复计算 成本压力&#…

精益数据分析(3/126):用数据驱动企业发展的深度解析

精益数据分析&#xff08;3/126&#xff09;&#xff1a;用数据驱动企业发展的深度解析 大家好&#xff01;一直以来&#xff0c;我都坚信在当今竞争激烈的商业环境中&#xff0c;数据是企业获得竞争优势的关键。最近深入研究《精益数据分析》这本书&#xff0c;收获颇丰&…

wpf ScaleTransform

在WPF中&#xff0c;ScaleTransform是用于实现元素缩放的核心类&#xff0c;属于System.Windows.Media命名空间下的变换类型。以下是其主要特性与使用方式的总结&#xff1a; ‌核心属性‌ ‌缩放比例‌ ScaleX&#xff1a;水平方向缩放比例&#xff08;默认1.0&#xff0c;即…

用纯Qt实现GB28181协议/实时视频/云台控制/预置位/录像回放和下载/事件订阅/语音对讲

一、前言 在技术的长河中探索&#xff0c;有些目标一旦确立&#xff0c;便如同璀璨星辰&#xff0c;指引着我们不断前行。早在2014年&#xff0c;我心中就种下了用纯Qt实现GB28181协议的种子&#xff0c;如今回首&#xff0c;一晃十年已逝&#xff0c;好在整体框架和逻辑终于打…

0x01、Redis 主从复制的实现原理是什么?

Redis 主从复制概述 Redis 的主从复制是一种机制&#xff0c;允许一个主节点&#xff08;主实例&#xff09;将数据复制到一个或多个从节点&#xff08;从实例&#xff09;。通过这一机制&#xff0c;从节点可以获取主节点的数据并与之保持同步。 复制流程 开始同步&#xf…

整活 kotlin + springboot3 + sqlite 配置一个 SQLiteCache

要实现一个 SQLiteCache 也是很简单的只需要创建一个 cacheManager Bean 即可 // 如果配置文件中 spring.cache.sqlite.enable false 则不启用 Bean("cacheManager") ConditionalOnProperty(name ["spring.cache.sqlite.enable"], havingValue "t…

深入探索如何压缩 WebAssembly

一、初始体积&#xff1a;默认 Release 构建 我们从最基础的构建开始&#xff0c;不开启调试符号&#xff0c;仅使用默认的 release 模式&#xff1a; $ wc -c pkg/wasm_game_of_life_bg.wasm 29410 pkg/wasm_game_of_life_bg.wasm这是我们优化的起点 —— 29,410 字节。 二…

多角度分析Vue3 nextTick() 函数

nextTick() 是 Vue 3 中的一个核心函数&#xff0c;它的作用是延迟执行某些操作&#xff0c;直到下一次 DOM 更新循环结束之后再执行。这个函数常用于在 Vue 更新 DOM 后立即获取更新后的 DOM 状态&#xff0c;或者在组件渲染完成后执行某些操作。 官方的解释是&#xff0c;当…

前端面试-自动化部署

基础概念 什么是CI/CD&#xff1f;在前端项目中如何应用&#xff1f;自动化部署相比手动部署有哪些优势&#xff1f;常见的自动化部署工具有哪些&#xff1f;举例说明它们的区别&#xff08;如Jenkins vs GitHub Actions&#xff09;。如何通过Git Hook实现自动化部署&#xf…

架构生命周期(高软57)

系列文章目录 架构生命周期 文章目录 系列文章目录前言一、软件架构是什么&#xff1f;二、软件架构的内容三、软件设计阶段四、构件总结 前言 本节讲明架构设计的架构生命周期概念。 一、软件架构是什么&#xff1f; 二、软件架构的内容 三、软件设计阶段 四、构件 总结 就…

GPTNet如何革新创意与效率

引言 人工智能正在以前所未有的速度改变我们的工作与生活方式&#xff0c;从智能写作到视觉创作&#xff0c;AI工具已成为不可或缺的伙伴。在众多平台中&#xff0c;GPTNet以其强大的功能整合和直观体验崭露头角。它不仅汇集了GPT系列、Claude、Grok、Gemini等顶级对话模型&am…

【计网】SSL/TLS核心原理

序言 在HTTP协议中&#xff0c;信息是明文传输的&#xff0c;因此为了通信安全就有了HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer)协议。HTTPS也是一种超文本传送协议&#xff0c;在HTTP的基础上加入了SSL/TLS协议&#xff0c;SSL/TLS依靠证书来验证服务端的…

Web Components 开发与集成

以下是关于 Web Components 开发与集成 的系统知识梳理,涵盖核心概念、高级特性、集成与优化等内容: 一、Web Components 核心概念 技术作用核心 APICustom Elements定义可复用的自定义 HTML 元素customElements.define()、生命周期钩子(connectedCallback 等)Shadow DOM封…

day26 学习笔记

文章目录 前言一、图像颜色转换1.HSV颜色空间2.颜色转换 二、灰度化1.最大值法2.平均值法3.加权均值法 三、二值化1.全局阈值法1.阈值法(THRESH_BINARY)2.反阈值法(THRESH_BINARY_INV)3.截断阈值法(THRESH_TRUNC)4.低阈值零处理(THRESH_TOZERO)5.超阈值零处理(THRESH_TOZERO_IN…

威锋VL822-Q7T10GHUB芯片适用于扩展坞显示器

一、概述 VL822-Q7T是VIA Lab&#xff08;威盛电子旗下专注于USB相关技术研发的子公司&#xff09;精心打造的一款高性能USB 3.1 Gen2集线器控制器芯片。在当今数字化时代&#xff0c;USB接口作为设备连接与数据传输的核心通道&#xff0c;其性能与稳定性至关重要。VL822-Q7T凭…

华为OD机试真题——最小的调整次数/特异性双端队列(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析&#xff1b; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式&#xff01; 2025华为OD真题目录全流程解析/备考攻略/经验分享 华为OD机试真题《最小的调…

关于 Spring Boot 微服务解决方案的对比,并以 Spring Cloud Alibaba 为例,详细说明其核心组件的使用方式、配置及代码示例

以下是关于 Spring Boot 微服务解决方案的对比&#xff0c;并以 Spring Cloud Alibaba 为例&#xff0c;详细说明其核心组件的使用方式、配置及代码示例&#xff1a; 关于 Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案! https://sca.aliyun.com/?spm7145af80…

常见的爬虫算法

1.base64加密 base64是什么 Base64编码&#xff0c;是由64个字符组成编码集&#xff1a;26个大写字母AZ&#xff0c;26个小写字母az&#xff0c;10个数字0~9&#xff0c;符号“”与符号“/”。Base64编码的基本思路是将原始数据的三个字节拆分转化为四个字节&#xff0c;然后…

B树、红黑树、B+树和平衡二叉树(如AVL树)的区别

B树、红黑树、B树和平衡二叉树&#xff08;如AVL树&#xff09;的区别及优缺点的总结&#xff1a; 1. 平衡二叉树&#xff08;AVL树&#xff09; 结构&#xff1a;二叉搜索树&#xff0c;每个节点的左右子树高度差不超过1。平衡方式&#xff1a;通过旋转&#xff08;左旋/右旋…

Python Cookbook-6.5 继承的替代方案——自动托管

任务 你需要从某个类或者类型继承&#xff0c;但是需要对继承做一些调整。比如&#xff0c;需要选择性地隐藏某些基类的方法&#xff0c;而继承并不能做到这一点。 解决方案 继承是很方便的&#xff0c;但它并不是万用良药。比如&#xff0c;它无法让你隐藏基类的方法或者属…