当前位置: 首页 > news >正文

pyhton基础【27】课后拓展

目录

一.动态绑定

动态语言的定义

在运行中给实例对象绑定(添加)属性

在运行中给类绑定(添加)属性

答案就是直接给Person类绑定属性:

运行中给实例对象绑定(添加)方法

完整代码示例

在代码运行中删除属性与方法

简单总结

二.__slots__方法

动态语言的概念

使用__slots__限制属性的创建

注意事项

简单总结

三.模块与包

概述

模块(Module)

包(Package)

函数入口

四.抽象基类

什么是抽象基类?

为什么使用抽象基类?

如何使用abc模块定义抽象基类?

简单总结


一.动态绑定
动态语言的定义

动态编程语言是高级程序设计语言的一个类别,在计算机科学领域已被广泛应用。它是一类在运行时可以改变其结构的语言。例如:新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。

动态语言目前非常具有活力。例如Python便是一个动态语言,除此之外如 PHP 、 Ruby 、 JavaScript 等也都属于动态语言,而 C语言 、C++ 等语言则不属于动态语言。

在运行中给实例对象绑定(添加)属性
>>> class Person:def __init__(self, name=None, age=None):self.name = nameself.age = age>>> p1 = Person("安娜", "20")

在这里,我们定义了一个类Person,在这个类里,定义了两个初始属性name和age,但是人还有性别啊!如果这个类不是你写的是不是你会尝试访问性别这个属性呢?

>>> p1.sex = "女"
>>> p1.sex
'女'

这里实际上就是动态给实例绑定属性

在运行中给类绑定(添加)属性
>>> p2 = Person("双双", "25")
>>> p2.sexTraceback (most recent call last):File "<pyshell#21>", line 1, in <module>p2.sex
AttributeError: Person instance has no attribute 'sex'

我们尝试打印p2.sex,发现报错,p2没有sex这个属性:给p1这个实例绑定属性对p2这个实例不起作用。那我们要给所有的Person的所有实例加上sex属性怎么办呢?

答案就是直接给Person类绑定属性:
>>>> Person.sex = None  # 给类Person添加一个属性
>>> p2 = Person("双双", "25")
>>> print(p2.sex)  # 如果p2这个实例对象中没有sex属性的话,那么就会访问它的类属性
None  # 可以看到没有出现异常
运行中给实例对象绑定(添加)方法

我们直接给Person绑定sex这个属性,然后实例化p2后,p2就有sex这个属性了! 那么方法呢?怎么绑定?

答:使用types.MethodType()方法

>>> class Person:def __init__(self, name=None, age=None):self.name = nameself.age = agedef eat(self):print("eat food")>>> def run(self, speed):print("%s在移动, 速度是%dkm/h" % (self.name, speed))>>> p3 = Person("夏洛", 24)
>>> p3.eat()
eat food
>>> 
>>> p3.run()
Traceback (most recent call last):File "<pyshell#5>", line 1, in <module>p3.run()
AttributeError: Person instance has no attribute 'run'
>>>
>>>
>>> import types
>>> p3.run = types.MethodType(run, p3)
>>> p3.run(180)
夏洛在移动,速度是180km/h
完整代码示例
import typesclass Person:num = 0def __init__(self, name=None, age=None):self.name = nameself.age = agedef eat(self):print("默认的实例方法...")print()# 定义函数, 且函数中的第一个参数为self
def run(self, speed):print("实例方法绑定...")print("%s在移动, 速度是 %d km/h" % (self.name, speed))print()# 定义函数, 且设置为类方法
@classmethod
def test_class(cls):print("类方法绑定...")print("num=%d" % cls.num)cls.num = 100print("num=%d" % cls.num)print()# 定义函数, 且设置为静态方法
@staticmethod
def test_static():print("静态方法绑定...")# 创建一个实例对象
p = Person("安娜", 18)
# 调用在class中的方法
p.eat()# 给这个对象添加实例方法
p.run = types.MethodType(run, p)
# 调用实例方法
p.run(180)# 给Person类绑定类方法
Person.test_class = test_class# 调用类方法
Person.test_class()# 给Person类绑定静态方法
Person.test_static = test_static
# 调用静态方法
Person.test_static()

运行结果:

默认的实例方法...实例方法绑定...
安娜在移动, 速度是 180 km/h类方法绑定...
num=0
num=100静态方法绑定...
在代码运行中删除属性与方法

删除的方法:

  1. del 对象.属性名
  2. delattr(对象, "属性名")
简单总结
  1. Python可以在运行的过程中,修改程序的运行结构,例如可以修改调用的函数等
  2. 对象中其实一切皆属性,方法其实也是属性,只不过这个可以进行调用而已,例如 实例对象名.属性名()
  3. 相对于动态语言,静态语言具有严谨性!所以,玩动态语言的时候,小心动态的坑!

那么怎么避免滥用动态绑定的这种情况呢? 请使用__slots__

二.__slots__方法
动态语言的概念

现在我们终于明白了动态语言与静态语言的不同:

  • 动态语言:可以在运行的过程中,修改代码
  • 静态语言:编译时已经确定好代码,运行过程中不能修改

如果我们想要限制实例的属性怎么办?比如,只允许对Person实例添加name和age属性。

使用__slots__限制属性的创建

为了达到限制的目的,Python允许在定义类的时候,定义一个特殊的__slots__属性,来限制该类创建的实例对象可以添加的属性

>>> class Person:__slots__ = ("name", "age")>>> P = Person()
>>> P.name = "teacher"  # 可以执行
>>> P.age = 20  # 可以执行
>>> P.score = 100  # 执行失败
Traceback (most recent call last):File "<pyshell#3>", line 1, in <module>
AttributeError: Person instance has no attribute 'score'
注意事项

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

In [67]: class Test(Person):...:     pass...:In [68]: t = Test()In [69]: t.score = 100
简单总结
  1. 为了限制随意给对象添加属性,可以使用__slots__来完成
  2. __slots__对子类不起作用
三.模块与包
概述

在Python中,模块和包是组织代码的两个基本构建块,它们帮助程序员以结构化的方式编写和管理代码。了解模块和包之间的区别以及如何使用它们,对于开发大型Python项目非常重要。

模块(Module)

模块是一个包含Python代码的文件。这个文件可以包含函数、类以及可执行的代码。模块的主要目的是将代码逻辑划分成不同的部分,并提供重用性。你可以在不同的Python程序中导入和使用模块中的函数和类。

导入模块通常使用import语句,例如:

import my_module

或者使用from...import...语句导入特定的函数:

from my_module import my_function
包(Package)

包是一种包含多个模块的层次性文件目录结构。它定义了一个由多个模块组成的Python应用程序的执行环境。包允许你将代码组织成一个易于管理和使用的结构。一个包通常由包含一个特殊__init__.py文件的目录组成,这个文件可以为空,其存在表明这个目录是一个Python包,可以包含其他模块和子包。

例如,一个名为my_package的包可能具有以下结构:

my_package/__init__.pymodule1.pymodule2.pysub_package/__init__.pysubmodule1.py

在这个结构中,my_package是顶级包,而sub_package是它的子包。包中的每个目录都需要一个__init__.py文件。

导入包中的模块,可以使用:

import my_package.module1

或者导入子包中的模块:

from my_package.sub_package import submodule1
函数入口

在Python程序中,函数入口通常指的是当一个程序文件被直接运行时最先执行的代码块。通过检查特殊的内置变量__name__来实现的。当一个Python文件被运行时,Python解释器将__name__的值设为"__main__",如果它作为模块被导入其他文件,则__name__的值将是模块的名称。

def main():# 你的程序代码passif __name__ == "__main__":main()

在以上代码中,main()函数作为程序的主要入口函数,而在文件的末尾,if __name__ == "__main__":检查确保了只有当文件被当做主程序运行时才调用main()函数。如果这个文件是作为模块被导入,main()函数将不会被执行,因此可以避免在模块导入时不必要的代码执行。这也提供了一种组织代码的有用方式,使得代码既可以被执行也可以被导入而不会引起副作用。

四.抽象基类
什么是抽象基类?
  • 抽象基类是一种只能被继承,不能被实例化的特殊类。
  • 它允许我们定义一些方法作为接口或者蓝图,而具体的子类需要实现这些方法。
  • ABCs提供了一种定义共有接口的手段。
为什么使用抽象基类?
  • 强制子类实现特定方法。
  • 提高代码的可读性和可维护性。
  • 支持多态性,即不同类的对象对同一方法响应不同的操作。
如何使用abc模块定义抽象基类?

Python的abc模块使得定义抽象基类变得简单。使用from abc import ABC, abstractmethod导入必要的类和方法,并且在定义抽象基类时,类应继承自ABC,之后通过装饰器@abstractmethod标记抽象方法。

from abc import ABC, abstractmethodclass GraphicShape(ABC):@abstractmethoddef area(self):passclass Circle(GraphicShape):def __init__(self, radius):self.radius = radiusdef area(self):return 3.14 * self.radius * self.radiuscircle = Circle(5)
print(circle.area())  # 输出圆的面积
  • 在这个例子中,GraphicShape是一个抽象基类,其中定义了一个抽象方法area()。
  • Circle类继承了GraphicShape并实现了area()方法。
简单总结
  • 抽象基类提供了一种强大的方式来定义接口和强制子类实现特定方法。
  • 使用abc模块可以轻松定义抽象基类和抽象方法。
http://www.dtcms.com/a/289842.html

相关文章:

  • 【华为机试】169. 多数元素
  • C++ STL中迭代器学习笔记
  • day057-docker-compose案例与docker镜像仓库
  • 元学习算法的数学本质:从MAML到Reptile的理论统一与深度分析
  • Vision Transformer (ViT) 介绍
  • 面试高频题 力扣 417. 太平洋大西洋水流问题 洪水灌溉(FloodFill) 深度优先遍历(dfs) 暴力搜索 C++解题思路 每日一题
  • 使用unsloth模型微调过程
  • 软件反调试(5)- 基于注册表实时调试器检测
  • MYSQL:从增删改查到高级查询
  • 数据结构-线性表的链式表示
  • 《P3398 仓鼠找 sugar》
  • 【1】YOLOv13 AI大模型-可视化图形用户(GUI)界面系统开发
  • 【实证分析】会计稳健性指标分析-ACF、CScore、Basu模型(2000-2023年)
  • MySQL锁(二) 共享锁与互斥锁
  • Filter快速入门 Java web
  • Compose笔记(三十七)--FilterChip
  • TVLT:无文本视觉-语言Transformer
  • c++ duiLib 显示一个简单的窗口
  • AMD处理器 5700G 矿卡RX580-8G 打英雄联盟怎么样
  • 洛谷 P10287 [GESP样题 七级] 最长不下降子序列-普及/提高-
  • 《P2680 [NOIP 2015 提高组] 运输计划》
  • 【66】MFC入门到精通——(CComboBox)下拉框选项顺序与添加顺序不一致
  • 前端静态资源免费cdn服务推荐
  • Dify极简部署手册
  • 30天打好数模基础-逻辑回归讲解
  • 7-大语言模型—指令理解:指令微调训练+模型微调
  • 【算法训练营Day15】二叉树part5
  • 编程研发工作日记
  • 050_Set接口(HashSet / TreeSet / LinkedHashSet)
  • 力扣面试150题--搜索插入位置