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

学习日志41 python

__getitem__方法

def __getitem__(self,pos):return range(0,30,10)[pos]
#这一段是什么意思?

这段代码定义了一个类的__getitem__方法,这是 Python 中的一个特殊方法,用于支持类的实例像列表、元组等可迭代对象一样通过索引(或切片)来访问元素。

具体来说:

  • range(0, 30, 10)创建了一个范围对象,包含的值是0, 10, 20(从 0 开始,到 30 为止但不包含 30,步长为 10)
  • [pos]表示使用传入的pos作为索引(或切片)来获取这个范围对象中的元素
  • 整个表达式的结果会作为__getitem__方法的返回值

例如,如果这个类的实例是obj

  • obj[0]会返回0(获取 range 的第 0 个元素)
  • obj[1]会返回10(获取 range 的第 1 个元素)
  • obj[2]会返回20(获取 range 的第 2 个元素)
  • obj[0:2]会返回range(0, 20, 10)(获取切片)

这个方法使得该类的实例可以像列表一样通过索引来访问预定义的这三个值(0、10、20)。

打印实际递增的索引

class FOO():def __init__(self):passdef __getitem__(self, pos):return range(0,30,10)[pos]
foo = FOO()for i in foo :print(i)#我能不能把pos打印出来啊

可以的,你可以在__getitem__方法中打印pos的值,这样就能看到迭代过程中实际使用的索引了。当你用for循环迭代对象时,Python 会自动调用__getitem__方法并传入从 0 开始的递增索引,直到触发IndexError为止。

修改后的代码如下:

python

运行

class FOO():def __init__(self):passdef __getitem__(self, pos):# 打印当前的pos值print(f"当前的pos是: {pos}")try:return range(0,30,10)[pos]except IndexError:# 当索引超出范围时,抛出IndexError终止迭代raisefoo = FOO()for i in foo:print(f"获取到的值: {i}\n")

运行这段代码会输出:

plaintext

当前的pos是: 0
获取到的值: 0当前的pos是: 1
获取到的值: 10当前的pos是: 2
获取到的值: 20当前的pos是: 3

可以看到,for循环迭代时会依次传入pos=0,1,2,3,当pos=3时,range(0,30,10)[3]会触发IndexError,循环循环就会终止。

2 enumerate()函数的输出格式

代码

data = ['周一', '周二', '周三', '周四']
for i,j in enumerate(data):print(i,j)

输出

0 周一
1 周二
2 周三
3 周四

enumerate() 函数用于将一个可迭代对象(如列表、元组、字符串等)组合为一个索引序列,同时返回索引和对应的元素。

它的输出格式是包含元组的可迭代对象,每个元组由两个元素组成:

  • 第一个元素:从指定起始值开始的整数索引(默认从 0 开始)
  • 第二个元素:可迭代对象中对应的元素

示例代码:

python

运行

# 基本用法(默认索引从0开始)
fruits = ['apple', 'banana', 'cherry']
for item in enumerate(fruits):print(item)# 输出:
# (0, 'apple')
# (1, 'banana')
# (2, 'cherry')# 指定起始索引(从1开始)
for item in enumerate(fruits, start=1):print(item)# 输出:
# (1, 'apple')
# (2, 'banana')
# (3, 'cherry')# 通常会解构元组直接获取索引和值
for index, value in enumerate(fruits):print(f"索引: {index}, 值: {value}")

简单来说,enumerate() 相当于为可迭代对象的每个元素添加了一个编号,方便在循环中同时获取位置和内容。

3 解释 Python 类方法和静态方法(@classmethod和@staticmethod)

代码

class Person:@classmethoddef eat(self):   print("吃饭")@staticmethoddef speak():print("说话")def run(self):print("走路")

测试

class Person:@classmethoddef eat(cls):print("吃饭")@staticmethoddef speak():print("说话")def run(self):print("走路")Person.speak()
Person.eat()
Person.run(Person())
Person.eat(Person())

输出

说话
吃饭
走路
Traceback (most recent call last):File "我的文件路径哈哈哈", line 16, in <module>Person.eat(Person())~~~~~~~~~~^^^^^^^^^^
TypeError: Person.eat() takes 1 positional argument but 2 were given

在 Python 中,@classmethod 和 @staticmethod 都是用于定义类方法的装饰器,但它们的作用和使用场景有所不同:

  1. @classmethod(类方法)

    • 第一个参数必须是类本身(通常命名为 cls,而不是 self
    • 可以访问和修改类的状态,能调用其他类方法
    • 可以通过类名直接调用,也可以通过实例调用
    • 常用于定义工厂方法,或者需要访问类属性的方法

    你代码中的 @classmethod 使用有个小问题,通常第一个参数应该用 cls 而不是 self,更规范的写法是:

    python

    运行

    @classmethod
    def eat(cls):  # 这里用cls更合适print("吃饭")
    
  2. @staticmethod(静态方法)

    • 不需要接收 self 或 cls 参数
    • 不能访问类状态或实例状态
    • 相当于一个普通函数,只是定义在类的命名空间里
    • 可以通过类名或实例调用
    • 常用于定义与类相关但不需要访问类状态的工具函数
  3. 普通实例方法(如你的 run 方法)

    • 第一个参数是实例本身(通常命名为 self
    • 可以访问和修改实例状态,也能访问类状态
    • 只能通过实例调用

简单来说:

  • 如果你需要操作类属性或调用其他类方法,用 @classmethod
  • 如果你需要一个与类相关但不依赖类或实例状态的函数,用 @staticmethod
  • 如果你需要操作实例属性,用普通实例方法(带 self 参数)

针对测试产生的问题

遇到的错误是因为类方法的调用方式不正确导致的。

当你调用 Person.eat(Person()) 时出现了错误,这是因为:

  1. @classmethod 装饰的方法已经默认接收一个类参数 cls
  2. 当你通过 Person.eat() 调用时,Python 会自动将类本身(Person)作为参数传给 cls
  3. 但你额外传入了 Person()(一个实例),导致参数数量变成了 2 个,从而引发 TypeError

正确的调用方式应该是:

python

运行

# 正确调用方式
Person.speak()   # 静态方法,无需参数
Person.eat()     # 类方法,自动传入类本身作为参数
Person().run()   # 实例方法,需通过实例调用
Person.eat()     # 类方法正确调用方式,无需额外传参

类方法有两种调用方式:

  • 通过类名调用:Person.eat()(推荐)
  • 通过实例调用:Person().eat()

这两种方式都会正确传递类参数 cls,而不需要你手动传递任何参数。

4 这个@是不能省略的吗(@classmethod 和 @staticmethod 这两个装饰器的 @ 符号不能省略

@classmethod 和 @staticmethod 这两个装饰器的 @ 符号不能省略

在 Python 中,以 @ 开头的是装饰器语法,它的作用是修改被装饰函数的行为。如果省略 @,就不再是装饰器调用,而只是普通的函数定义,会导致:

  1. 函数性质改变

    • 没有 @classmethoddef eat(cls): 会被当作普通实例方法(但参数用了 cls 会造成混淆)
    • 没有 @staticmethoddef speak(): 会被当作需要 self 参数的实例方法,调用时会报错
  2. 调用方式出错

    python

    运行

    class Person:# 省略 @classmethod 后,eat 变成普通实例方法def eat(cls):print("吃饭")# 省略 @staticmethod 后,speak 变成需要 self 的实例方法def speak():print("说话")Person.eat()  # 报错:缺少 self 参数
    Person.speak()  # 报错:缺少 self 参数
    

简单说,@ 是装饰器语法的标志,省略后就无法实现「类方法」和「静态方法」的特殊功能了,必须严格按照 @装饰器名 的格式使用。

5 装饰器语法

装饰器(Decorator)是 Python 中一种特殊的语法,用于在不修改原函数代码的前提下,为函数或类添加额外功能

它的本质是一个接受函数作为参数,并返回新函数的高阶函数。

装饰器使用 @装饰器名 的形式放在函数或类的定义上方,这就是装饰器语法的标志。

举个简单例子理解:

比如我们想给一个函数添加「执行前打印日志」的功能,可以用装饰器实现:

python

运行

# 定义一个装饰器(本质是函数)
def log_decorator(func):def wrapper():print("函数开始执行...")  # 额外功能func()  # 执行原函数print("函数执行结束...")  # 额外功能return wrapper# 使用装饰器(@语法)
@log_decorator
def say_hello():print("Hello, 装饰器!")# 调用函数
say_hello()

运行结果:

plaintext

函数开始执行...
Hello, 装饰器!
函数执行结束...

装饰器的作用:

  1. 代码复用:将通用功能(如日志、权限验证、计时等)抽离成装饰器,多个函数可以共享。
  2. 不修改原函数:符合「开放 - 封闭原则」,在扩展功能时不改变原有代码。
  3. 简化代码:用 @装饰器名 一行代码即可为函数添加功能,清晰直观。

常见应用场景:

  • 日志记录(如函数调用时间、参数等)
  • 权限验证(如判断用户是否登录)
  • 性能测试(如计算函数执行时间)
  • 缓存处理(如缓存函数返回结果)

像之前学的 @classmethod 和 @staticmethod 就是 Python 内置的装饰器,它们的作用是把普通函数「装饰」成类方法或静态方法。

http://www.xdnf.cn/news/1406143.html

相关文章:

  • Linux/UNIX系统编程手册笔记:文件I/O、进程和内存分配
  • vue2下拉菜单
  • 【小宁学习日记5 PCB】电路定理
  • 9. 函数和匿名函数(一)
  • 快消品牌如何用 DAM 管理万张素材?
  • 【光照】[光照模型]是什么?以UnityURP为例
  • C++的反向迭代器
  • BEV-VAE
  • 二进制方式安装部署 Logstash
  • Java试题-选择题(23)
  • 【Linux基础】深入理解计算机启动原理:MBR主引导记录详解
  • 并发编程:Java中的多线程与线程池!
  • 魔方的使用
  • LangGraph 深度解析(二):掌握 LangGraph 函数式 API 的状态化 AI 工作流
  • 每日算法题【二叉树】:堆的实现、堆排序的实现、文件中找TopK
  • [光学原理与应用-338]:ZEMAX - Documents\Zemax\Samples
  • 吴恩达机器学习作业九:kmeans聚类
  • 2025最确定性的答案:AI+IP的结合
  • CNB远程部署和EdgeOne Pages
  • 恶补DSP:3.F28335的ePWM模块
  • Wheat Gene ID Convert Tool 小麦中国春不同参考基因组GeneID转换在线工具
  • TensorFlow 深度学习 | 使用底层 API 实现模型训练(附可视化与 MLP)
  • 「日拱一码」066 深度学习——Transformer
  • ADB常用命令大全
  • Linux中的Shell编程 第一章
  • 第09章 t检验:两独立样本t检验
  • 模拟|双指针
  • 【CUDA进阶】MMA分析Bank Conflict与Swizzle(下)
  • python pyqt5开发DoIP上位机【介绍】
  • 【cancelToken取消重复请求】