(8)揭示Python编程精髓:深潜继承与多态的奇幻之旅

目录

  • 1. 命名空间与作用域
    • 1.1 命名空间概述
    • 1.2 作用域
    • 1.2.1 局部作用域
    • 1.2.2 全局作用域
    • 1.2.3 修改全局变量
    • 1.2.4 嵌套作用域
  • 2. 继承
  • 3. 多态(Polymorphism)

1. 命名空间与作用域

1.1 命名空间概述

命名空间是一个从名字到对象的映射,它在Python程序中定义了一系列变量的名称。每个命名空间都是一个字典的实现,虽然字典是直接由用户创建的,但是命名空间的创建和使用完全由解释器来控制。
在这里插入图片描述

1.2 作用域

在Python编程中,作用域(Scope)是指程序中定义变量的区域,决定了变量的可见性和生命周期。它规定了程序中哪些区域能够访问特定的变量名称。

Python中的作用域主要有四种:

  • 内置作用域(Built-in Scope):内置作用域包含了Python内置的函数和异常类,以及内置的函数和异常名(如abs(), int(), list(), Exception等)。这个作用域在Python解释器启动时创建,每个模块都可以访问内置作用域。
    然而,在Python中,我们通常不会直接提及“内置作用域”(Built-in Scope)作为一个独立的作用域级别,尽管技术上内置名称(如内置函数和异常等)确实存在于一个特定的命名空间中。然而,当我们讨论作用域时,我们通常指的是全局作用域、局部作用域和(可能的)嵌套作用域。

  • 局部作用域(Local Scope):局部作用域是在函数或方法内部定义的变量的作用域。函数参数和函数内部定义的变量都属于局部作用域。局部变量在函数调用时创建,在函数返回时销毁。

  • 全局作用域(Global Scope):全局作用域是最外层的命名空间,在模块级别定义的变量属于全局作用域。全局作用域在程序执行时创建,程序的所有模块都可以访问全局作用域中的变量。

  • 嵌套作用域(Enclosing Scope):在嵌套函数中,外部函数定义的变量对内部函数而言是可见的,但仅当内部函数没有定义同名的局部变量时。这个作用域在嵌套函数或类定义时创建。

在Python中,变量的访问遵循LEGB规则,即Local(局部作用域)-> Enclosing(嵌套作用域,如果有的话)-> Global(全局作用域)-> Built-in(内置作用域)。这意味着,在查找一个变量时,Python会首先在当前的作用域中查找,如果找不到,它会向上一级作用域查找,直到找到为止或者引发NameError

需要注意的是,Python中没有块级作用域(Block Scope),也就是说,在ifforwhile语句块中定义的变量,实际上是定义在包含该语句块的函数或模块的全局作用域或局部作用域中。这是与其他一些编程语言(如C++或Java)不同的地方。

1.2.1 局部作用域

在Python中,局部作用域通常指的是在函数内部定义的变量所存在的作用范围。这些变量只能在定义它们的函数内部被访问。当函数被调用时,这些局部变量被创建,并在函数执行完毕后被销毁。

为了说明局部作用域在金融领域的应用,我们可以考虑一个简单的例子:
一个计算复利(Compound Interest)的函数。在这个函数中,我们将使用局部变量来存储如利率(interest rate)、本金(principal amount)、年份(years)和计算结果(future value)等信息。

def calculate_compound_interest(principal, annual_interest_rate, years):# 这些变量是局部变量,只能在calculate_compound_interest函数内部访问# 假设一年有365天,这是为了简化计算(实际中应考虑闰年等情况)days_in_year = 365# 将年利率转换为日利率daily_interest_rate = annual_interest_rate / (100 * days_in_year)# 使用复利公式计算未来的价值future_value = principal * ((1 + daily_interest_rate) ** (days_in_year * years))# 返回计算结果return future_value# 示例:计算10000元本金在5%年利率下,10年后的复利
principal = 10000
annual_interest_rate = 5
years = 10
result = calculate_compound_interest(principal, annual_interest_rate, years)
print(f"未来的价值是: {result:.2f}元")

在这个示例中,days_in_yeardaily_interest_ratefuture_value都是局部变量。它们在calculate_compound_interest函数内部被定义和使用,并且在函数执行完毕后被销毁。注意,这些变量在函数外部是不可见的(即不能从函数外部直接访问)。这就是局部作用域的基本原理。

1.2.2 全局作用域

全局作用域是整个Python脚本中都可以访问的作用域。在这里,我们将定义全局变量total_investmenttotal_return

示例:假设我们有一个投资组合,我们想要计算其投资回报率(ROI,Return on Investment)。我们可以定义全局变量来存储投资的总金额和回报金额,然后在函数中计算ROI。

# 全局变量
total_investment = 100000  # 初始投资金额为10万
total_return = 15000  # 假设回报金额为1万5def calculate_roi():# 函数内部的计算将在局部作用域中进行roi = (total_return / total_investment) * 100  # 计算ROIprint(f"投资回报率为:{roi}%")# 调用函数,计算并打印ROI
calculate_roi()

在这个例子中,total_investmenttotal_return是全局变量,它们可以在全局作用域中被任何代码访问。我们在calculate_roi函数内部引用了这两个全局变量来计算ROI。

1.2.3 修改全局变量

如果我们想在函数内部修改全局变量的值,我们需要使用global关键字来声明。但是,在大多数情况下,最好避免在函数内部修改全局变量,因为这可能导致代码更难理解和维护。不过,为了完整解释,我们还是给出一个例子:

# 全局变量
total_investment = 100000  # 初始投资金额为10万
total_return = 15000  # 假设回报金额为1万5def update_investment_and_return(new_investment, new_return):global total_investment, total_returntotal_investment = new_investment  # 更新投资金额total_return = new_return  # 更新回报金额calculate_roi()  # 重新计算并打印ROI# 调用函数,更新投资金额和回报金额,并重新计算ROI
update_investment_and_return(120000, 20000)

在这个例子中,我们定义了一个新函数update_investment_and_return,它接受新的投资金额和回报金额作为参数,并使用global关键字声明了要修改的全局变量。然后,它更新了这些全局变量的值,并重新计算了ROI。

1.2.4 嵌套作用域

在Python中,嵌套作用域通常与嵌套函数相关,即一个函数内部定义的另一个函数。在这种情况下,内部函数可以访问其外部函数(即包含它的函数)的局部作用域中的变量,这被称为封闭作用域或外部作用域。

下面是一个使用嵌套作用域和金融示例的Python代码。我们将创建一个计算贷款支付金额的函数,并在其中定义一个嵌套的利率计算函数。

def calculate_monthly_payment(principal, annual_rate, term_years):# 将年利率转换为月利率def calculate_monthly_rate(annual_rate):return annual_rate / 12 / 100# 嵌套函数内部使用外部函数的变量monthly_rate = calculate_monthly_rate(annual_rate)# 贷款期数(月份)total_payments = term_years * 12# 使用公式计算每月支付金额(这里简化处理,没有包含复杂的还款计算)# 注意:这里仅用于示例,真实情况中需使用专门的贷款公式monthly_payment = principal * monthly_rate / (1 - (1 + monthly_rate) ** -total_payments)return round(monthly_payment, 2)  # 保留两位小数# 示例:计算50,000元的贷款在5%的年利率下,10年期限的每月支付金额
loan_amount = 50000
annual_interest_rate = 5
loan_term = 10
monthly_payment = calculate_monthly_payment(loan_amount, annual_interest_rate, loan_term)
print(f"每月需要支付: {monthly_payment} 元")

在上面的示例中,calculate_monthly_payment 函数是一个外部函数,它接收贷款本金、年利率和贷款期限(年)作为参数。这个函数内部定义了一个嵌套函数 calculate_monthly_rate,用于将年利率转换为月利率。嵌套函数可以访问其外部函数 calculate_monthly_payment 的作用域中的变量 annual_rate。然后,外部函数使用嵌套函数计算出的月利率来计算每月的支付金额,并返回结果。

注意,虽然嵌套函数在这里很有用,但它不是必需的。你也可以直接在 calculate_monthly_payment 函数中编写计算月利率的代码,而不是使用嵌套函数。但是,当逻辑变得更加复杂或者你需要将一部分逻辑封装起来以便在多个地方重用时,嵌套函数就会非常有用。

2. 继承

在Python中,继承是一种面向对象编程的重要特性,它允许我们创建一个新的类(称为子类或派生类),这个类继承自一个或多个已存在的类(称为父类或基类)。子类可以继承父类的属性和方法,并可以添加新的属性和方法或重写父类的方法。

在金融领域,继承可以用于创建不同种类的金融产品类,例如,一个基本的金融产品类可以被继承以创建具体的股票类、债券类、基金类等。下面是一个使用Python继承及金融领域的示例。

# 定义一个基本的金融产品类
class FinancialProduct:def __init__(self, name, price):self.name = nameself.price = pricedef buy(self):print(f"购买了 {self.name},价格为 {self.price} 元。")def sell(self):print(f"出售了 {self.name},价格为 {self.price} 元(仅为示例,实际卖出价格可能不同)。")# 继承自金融产品类的股票类
class Stock(FinancialProduct):def __init__(self, name, price, symbol):super().__init__(name, price)  # 调用父类的初始化方法self.symbol = symbol  # 股票特有的属性:股票代码def dividend(self, amount):print(f"股票 {self.name} (代码 {self.symbol}) 分红 {amount} 元。")# 创建一个股票对象并测试其方法
if __name__ == "__main__":apple_stock = Stock("苹果公司股票", 150.0, "AAPL")apple_stock.buy()apple_stock.sell()apple_stock.dividend(3.0)# 尝试使用基类的方法创建一个普通的金融产品(不是股票)bond = FinancialProduct("国债", 100.0)bond.buy()bond.sell()

在这个例子中,我们定义了一个FinancialProduct类作为基类,它包含了金融产品的一些通用属性和方法,如name(产品名称)、price(产品价格)、buy(购买)和sell(出售)。

然后我们定义了一个Stock类,它继承自FinancialProduct类。Stock类添加了一个额外的属性symbol(股票代码)和一个新的方法dividend(分红)。Stock类的__init__方法调用了父类FinancialProduct__init__方法以设置通用的属性和方法,然后添加了Stock特有的属性。

__main__部分,我们创建了一个Stock对象和一个FinancialProduct对象,并分别调用了它们的方法。这展示了子类如何使用继承来重用父类的代码,并添加自己的特定属性和方法。

3. 多态(Polymorphism)

多态是面向对象编程的三大特性之一(继承、封装和多态),它意味着不同的对象对同一消息做出不同的响应。在Python中,多态性主要通过方法重写(Overriding)和方法重载(Overloading,虽然Python本身不支持传统的函数重载)来实现。

但是,在Python中,我们通常通过定义接口(通过抽象基类实现)或使用鸭子类型(duck typing)来实现多态性。

抽象基类允许你定义接口,子类可以继承这些接口并实现所需的方法。而鸭子类型则是一种动态类型方式,它并不关心对象的类型,只关注对象是否拥有某些方法或属性。

下面是一个使用Python的抽象基类和鸭子类型来展示金融领域多态性的示例:

首先,我们定义一个抽象基类FinancialProduct,它定义了一个计算回报率的接口:

from abc import ABC, abstractmethodclass FinancialProduct(ABC):@abstractmethoddef calculate_return(self):pass

接着,我们定义两个具体的金融产品类Stock和Bond,它们继承自FinancialProduct并实现了calculate_return方法:

class Stock(FinancialProduct):def __init__(self, name, current_price, purchase_price):self.name = nameself.current_price = current_priceself.purchase_price = purchase_pricedef calculate_return(self):return (self.current_price - self.purchase_price) / self.purchase_priceclass Bond(FinancialProduct):def __init__(self, name, face_value, coupon_rate, years_to_maturity):self.name = nameself.face_value = face_valueself.coupon_rate = coupon_rate / 100  # 将百分比转换为小数self.years_to_maturity = years_to_maturitydef calculate_return(self):# 这里为了简化,我们假设每年回报率是固定的return self.coupon_rate

现在我们可以定义一个函数来处理这些金融产品,这个函数不关心产品的具体类型,只要它实现了calculate_return方法即可:

def show_return(product):print(f"产品 {product.name} 的回报率为: {product.calculate_return() * 100:.2f}%")# 创建金融产品实例
stock = Stock("苹果公司股票", 150.0, 100.0)
bond = Bond("五年期国债", 1000.0, 5.0, 5)# 调用函数,展示回报率
show_return(stock)
show_return(bond)

在这个例子中,show_return函数展示了多态性。它接受一个FinancialProduct类型的参数,但实际上可以接受任何实现了calculate_return方法的对象。这就是鸭子类型的体现:如果它走起路来像鸭子(即拥有calculate_return方法),那么我们就可以把它当作鸭子来处理。

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

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

相关文章

Qt:19.浮动窗口/子窗口(子窗口介绍、代码方式创建子窗口、设置子窗口标题、为子窗口添加控件、设置子窗口停靠位置)

目录 1.子窗口介绍: 2.代码方式创建子窗口: 3.设置子窗口标题: 4.为子窗口添加控件: 5.设置子窗口停靠位置。 1.子窗口介绍: 在 Qt 中,可以创建和管理子窗口(子窗口体)以实现多窗…

图片怎么制作成长期可用的活码?扫码提供图片预览的制作技巧

现在图片的尺寸和清晰度的质量越来越高,相对应的会占用更多的存储空间,现在很多人会将图片存入云端后,通过生成二维码的方式,扫码来查看图片内容。图片转换二维码有利于将图片分享给其他人查看,还能够节省更多的空间&a…

SpringBoot自己开发一个starter

提示:本文主要讲述如何自行开发一个SpringBoot的starter 文章目录 目录 文章目录 前言 一、Starter是什么 二、创建一个SpringBoot项目 1.创建一个基本的SpringBoot项目 2.选择要下载的库 三、设置项目 1.提示 2.配置pom.xml 3.重点代码 1.创建一个User类…

16.x86游戏实战-汇编指令push pop pushad popad

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 工具下载: 链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

【第29章】MyBatis-Plus之分页插件

文章目录 前言一、支持的数据库二、配置方法三、属性介绍四、自定义 Mapper 方法中使用分页五、其他注意事项六、Page 类七、实战1. 配置类2. 分页类3. 测试 总结 前言 MyBatis-Plus 的分页插件 PaginationInnerInterceptor 提供了强大的分页功能,支持多种数据库&a…

Windows电脑安装Python结合内网穿透轻松搭建可公网访问私有网盘

文章目录 前言1.本地文件服务器搭建1.1.Python的安装和设置1.2.cpolar的安装和注册 2.本地文件服务器的发布2.1.Cpolar云端设置2.2.Cpolar本地设置 3.公网访问测试4.结语 前言 本文主要介绍如何在Windows系统电脑上使用python这样的简单程序语言,在自己的电脑上搭建…

电力需求预测挑战赛笔记 Taks1 跑通baseline

#AI夏令营 #Datawhale #夏令营 赛题 一句话介绍赛题任务可以这样理解赛题: 【训练时序预测模型助力电力需求预测】 电力需求的准确预测对于电网的稳定运行、能源的有效管理以及可再生能源的整合至关重要。 赛题任务 给定多个房屋对应电力消耗历史 N 天的相关序列数…

09.AOP-尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解)

现有代码缺陷 针对带日志功能的实现类,我们发现有如下缺陷: 对核心业务功能有干扰,导致程序员在开发核心业务功能时分散了精力附加功能分散在各个业务功能方法中,不利于统一维护 解决思路 解决核心:解耦。把附加功能从…

从零开始读RocketMq源码(三)Broker存储Message流程解析

目录 前言 准备 消息载体CommitLog 文件持久化位置 源码解析 broker消息对象MessageExtBrokerInner 异步存储message CommitLog的真相 创建MappedFile文件 加入异步刷盘队列 Message异步存储MappedByteBuffer 总结 前言 在面试中我们经常会听到这样的回答&#x…

国产化趋势下源代码数据防泄密的信创沙盒的方案分享

随着国产化的大力推进,越来越多的企事业单位在逐步替换Windows、Linux等操作系统的使用。那么什是国产化了?国产化是指在产品或服务中采用国内自主研发的技术和标注,替代过去依赖的他国的产品和服务,国产化又被称之为“信创”&…

GitLab CI/CD实现项目自动化部署

1 GitLab CI/CD介绍 GitLab CI/CD 是 GitLab 中集成的一套用于软件开发的持续集成(Continuous Integration)、持续交付(Continuous Delivery)和持续部署(Continuous Deployment)工具。这套系统允许开发团队…

vue里实现点击按钮回到页面顶部功能,博客必备!

效果 步骤 1-标签结构 动态绑定样式style&#xff0c;监听点击事件&#xff0c;后续控制opacity透明度。和滚动距离 <div class"toTop" :style"dynamicStyles" click"toTop"><!--<i class"fa fa-arrow-up"></i>…

超简单的通配证书签发工具,免费,无需安装任何插件到本地

常见的acme.sh 或者 lego等工具需要配置&#xff0c;安装不灵活&#xff0c;续签需要配置计划任务&#xff0c;签发单域名证书或者通配证书需要不同的指令和配置&#xff0c;繁琐&#xff0c;如果自己程序想要对接签发证书的api有的不支持&#xff0c;有的用起来繁琐。 最近发…

【VIVADO SDK调试遇到DataAbortHandler】

问题 SDK调试遇到DataAbortHandler问题。 运行后不显示结果&#xff0c;debug模式下发现进入DataAbortHandler异常函数。程序中存在大数组。 原因:SDK默认的堆栈为1024bytes,需要将堆栈调大。 修改方法&#xff1a; 解决:对application中src下的lscript.ld双击&#xff0c;…

Linux 程序卡死的特殊处理

一、前言 Linux环境。 我们在日常编写的程序中&#xff0c;可能会出现一些细节问题&#xff0c;导致程序卡死&#xff0c;即程序没法正常运行&#xff0c;界面卡住&#xff0c;也不会闪退... 当这种问题出现在客户现场&#xff0c;那就是大问题了。。。 当我们暂时还无法排…

如何定量选择孔销基准?-DTAS来帮你!

在当今快速发展的工程领域&#xff0c;公差仿真的作用日渐重要&#xff0c;在公差仿真中&#xff0c;基准体系的选择对于最终结果更是至关重要。基准体系不同可能导致仿真过程中的参数计算、误差分析以及最终的工程设计都有所不同。基准体系作为评估和比较的参照&#xff0c;直…

Suricata引擎二次开发之命中规则定位

二开背景 suricata是一款高性能的开源网络入侵检测防御引擎&#xff0c;旨在检测、预防和应对网络中的恶意活动和攻击。suricata引擎使用多线程技术&#xff0c;能够快速、准确地分析网络流量并识别潜在的安全威胁&#xff0c;是众多IDS和IPS厂商的底层规则检测模块。 前段时间…

强制升级最新系统,微软全面淘汰Win10和部分11用户

说出来可能不信&#xff0c;距离 Windows 11 正式发布已过去整整三年时间&#xff0c;按理说现在怎么也得人均 Win 11 水平了吧&#xff1f; 然而事实却是&#xff0c;三年时间过去 Win 11 占有率仅仅突破到 29%&#xff0c;也就跳起来摸 Win 10 屁股的程度。 2024 年 6 月 Wi…

【Linux】磁盘性能压测-FIO工具

一、FIO工具介绍 fio&#xff08;Flexible I/O Tester&#xff09;是一个用于评估计算机系统中 I/O 性能的强大工具。 官网&#xff1a;fio - fio - Flexible IO Tester 注意事项&#xff01; 1、不要指定文件系统名称&#xff08;如/dev/mapper/centos-root)&#xff0c;避…

react启用mobx @decorators装饰器语法

react如果没有经过配置&#xff0c;直接使用decorators装饰器语法会报错&#xff1a; Support for the experimental syntax ‘decorators’ isn’t currently enabled 因为react默认是不支持装饰器语法&#xff0c;需要做一些配置来启用装饰器语法。 step1: 在 tsconfig.js…