[Day2]PythonAdvanced-学习笔记-迭代器/生成器/上下文管理器/属性描述符/元类

news/2024/11/28 0:24:40/文章来源:https://www.cnblogs.com/m-t-arden/p/18573362

[PythonAdvanced] 学习笔记 - Day 2

Overview

Date: 2024-11-27 Time Spent: 6 hours

Topics: Decorators Difficulty: ⭐⭐⭐ (1-5 ⭐)

What I Learned Today

  1. [Generator & Iterator 迭代器和生成器]

    • Main points:

      當我們使用循環來循環某些內容時,稱為迭代。它是進程本身的名稱。迭代器是一個對象,它使程式設計師能夠遍歷容器,特別是列表。迭代器用于遍历集合中的元素,但它本身并不存储元素,而是提供了一种按顺序访问集合元素的方式。因此,说迭代器更像是一个访问元素的接口。

      生成器(generator)是一种特殊的迭代器,它使用函数来产生序列中的元素。生成器函数使用 yield 关键字来暂停函数执行并产生一个值,然后在下一次迭代时从上次暂停的位置继续执行。生成器的一个关键特性是它们可以“惰性求值”(lazy evaluation),即只在需要时才生成值。

    • Generator Example code

      # Generators are best for calculating large sets of results (particularly calculations involving loops themselves) where you don’t want to allocate the memory for all results at the same time. 
      # generator version
      def fibon(n):a = b = 1for i in range(n):yield aa, b = b, a + b
      for x in fibon(1000000):print(x)
      
    • Iterator Example code

      int_var = 1779
      iter(int_var)
      # Output: Traceback (most recent call last):
      #   File "<stdin>", line 1, in <module>
      # TypeError: 'int' object is not iterable
      # This is because int is not iterablemy_string = "Yasoob"
      my_iter = iter(my_string)
      print(next(my_iter))
      # Output: 'Y'
      
  2. [Classes 类]

    • Main points: 类变量用于在类的不同实例之间共享的数据。

    • Classes Example code

      class Cal(object): #不可变函数使用过程中不会出现污染# pi is a class variablepi = 3.142def __init__(self, radius):# self.radius is an instance variableself.radius = radiusdef area(self):return self.pi * (self.radius ** 2)a = Cal(32)
      a.area()
      # Output: 3217.408
      a.pi
      # Output: 3.142
      a.pi = 43
      a.pi
      # Output: 43
      
    • __init__ 是类初始值设定项。每当创建类的实例时,都会调用其 __init__ 方法。

      class GetTest(object):def __init__(self, name):print('Greetings!! {0}'.format(name))def another_method(self):print('I am another method which is not'' automatically called')a = GetTest('yasoob')
      # Output: Greetings!! yasoob# Try creating an instance without the name arguments
      b = GetTest()
      Traceback (most recent call last):File "<stdin>", line 1, in <module>
      TypeError: __init__() takes exactly 2 arguments (1 given)
      
    • __getitem__ 在类中实现 get item 允许其实例使用 [](索引器)运算符。

      class GetTest(object):def __init__(self):self.info = {'name':'Yasoob','country':'Pakistan','number':12345812}def __getitem__(self,i):return self.info[i]foo = GetTest()foo['name']
      # Output: 'Yasoob'foo['number']
      # Output: 12345812
      
  3. [Meta classes 元类]

    • Main points: 类定义了对象的行为,而元类则定义了类的行为。通过元类,我们可以改变类的创建方式,自动添加属性或方法,实现类的注册,强制API一致性等。

    • Meta classes Example code

      class MyMeta(type):def __new__(cls, name, bases, dct):x = super().__new__(cls, name, bases, dct)x.attr = 100return xclass MyClass(metaclass=MyMeta):passprint(MyClass.attr)  # 输出: 100
      
  4. [Descriptor 属性描述符]

    • Main points:

      描述符是一个类,只要内部定义了__get____set____delete__中的一个或多个方法,就可以被视为描述符。如果描述符同时定义了__set____get__方法(或只定义了__set__方法),则被称为数据描述符。数据描述符的优先级高于实例属性。如果描述符只定义了__get__方法(或未定义__set__方法),则被称为非数据描述符。

    • Descriptor Example code

      class Descriptor:def __set_name__(self, owner, name):self.name = f"__{name}__"def __get__(self, instance, owner):return getattr(instance, self.name, None)def __set__(self, instance, value):setattr(instance, self.name, value)def __delete__(self, instance):raise AttributeError("delete is disabled")class X:data = Descriptor()x = X()
      x.data = 100
      print(x.data)  # 输出: 100
      print(x.__dict__)  # {'__data__': 100}
      
    • Example code

      def do_twice(func):def wrapper_do_twice(*args, **kwargs):func(*args, **kwargs)func(*args, **kwargs)return wrapper_do_twice@do_twice # greet = do_twice(greet)
      def greet(name):print(f"Hello {name}")
      >>> greet(name = "Mia")
      
    • Example code

  5. [Context Managers 上下文管理器]

    • Main points: 上下文管理器可讓您在需要時精確地指派和釋放資源。上下文管理器最廣泛使用的範例是with語句。

      举例:打開文件,向其中寫入一些數據,然後關閉它

      with open('some_file', 'w') as opened_file:opened_file.write('Hola!')Silimar as following code:file = open('some_file', 'w')
      try:file.write('Hola!')
      finally:file.close()
      
    • File Example code

      #by defining __enter__ and __exit__ methods we can use our new class in a with statement.
      class File(object):def __init__(self, file_name, method):self.file_obj = open(file_name, method)def __enter__(self):return self.file_objdef __exit__(self, type, value, traceback):self.file_obj.close()with File('demo.txt', 'w') as opened_file:opened_file.write('Hola!')
      
    • 以生成器的形式调用上下文管理器

      Example code

      from contextlib import contextmanager@contextmanager
      def open_file(name):f = open(name, 'w')try:yield ffinally:f.close()
      with open_file("test.txt") as f:f.write("Hi")
      

Code Practice

from torch.utils.hipify.hipify_python import valuetemp_str = "YouAreNumerousStars"
my_iter = iter(temp_str)  # 转换为迭代器# for i in my_iter: #输出字符
# print(i)def fibo(n):a = b = 1for i in range(n):yield a  # 将a的值返回给调用者fibo,然后暂停观察是否还需要进行下一次迭代# 如果需要下一次迭代,就继续运行a, b = b, a + ba, b = b, a + b  # a=b,b=a+b# for i in fibo(5):  # 调用斐波那契数列需要使用迭代才能调用
# print(i)class cal_area(object):pi = 3.142def __init__(self, r):self.r = rdef area(self):return self.pi * self.r * self.r  # 需要给变量前面加上self# a = cal_area(5)
# print(a.area())class test_info(object):def __init__(self, **kwargs):self.info = {**kwargs}def __getitem__(self, item):return self.info[item]myinfo = {"name": "Arden", "position": 'student'}
a = test_info(**myinfo)
# print(a.__getitem__("name"))"""
元类是创建类的类。比如元类为Mymeta,其中的x为新建的类。
"""
class Mymeta(type):  # type是内建的元类,用于创建类对象def __new__(cls, name, bases, dct):  # 允许我们自定义类的创建过程"""注:以下内容为局部变量,非属性cls:指的是当前正在创建的类(即MyMeta自身)。name:是类的名称。bases:是类的基类元组(由于在Python 3中,所有类默认继承自object,所以这里可能不显式包含object)。dct:是一个字典,包含了类定义中所有的属性和方法。"""x = super().__new__(cls, name, bases, dct)# 新建类x,super()返回了母函数(Mymeta的上一级type)x.attrs = 100 #给x类添加属性attrs,赋值100return x
class MyClass(metaclass=Mymeta): #pass  # 占位符语句
#print(MyClass.name) 局部变量无法运行
#print(MyClass.__name__) #__name__是Python自动为每个类设置的,用于存储类的名称#描述符只要定义了__set__,被称为数据描述符;没有定义__set__为实例描述符
#数据优先级>实例优先级
class Descriptor: #定义描述符def __set_name__(self, owner, name):#描述符被分配给了哪个类(owner)以及它在该类中的名称(name)self.name = f"__{name}__"  #加下划线是为了符合描述符在类中被赋予的名称def __get__(self, instance, owner):#获取描述符的值。instance 是尝试访问描述符的实例(如果有的话)。return getattr(instance, self.name) #从实例的 __dict__ 中获取以 self.name的值,并返回它def __set__(self, instance, value):#设置描述符的值setattr(instance, self.name, value)#在实例的 __dict__ 中设置以 self.name命名的属性的值为 valuedef __delete__(self, instance):delattr(instance, self.name)#从实例的 __dict__ 中删除以self.name命名的属性。class X:"""data的类属性是 Descriptor 类的一个实例。它会自动为 X的实例提供 __get__, __set__, 和 __delete__ 方法所定义的行为。"""data=Descriptor()name=Descriptor()
x=X()
x.data=100
x.name="Arden"
#print(x.data, x.name)
#print(x.__dict__)"""
使用上下文管理器的好处带来了更好的异常处理、更简洁的代码和更高的可维护性。
"""
class File(): #可以省略括号中的object,因为在Python3中是默认的def __init__(self, file_name):#初始化File,每次使用都会实现以下代码self.file_name = file_nameself.file_obj = open(self.file_name, "w") #按file_name以写入模式打开文件def __enter__(self):return self.file_obj#在 with 语句中,这个返回的对象会被赋值给 as 关键字后面的变量def __exit__(self, exc_type, exc_val, exc_tb):#当 with 语句块执行完毕或发生异常时,会自动调用这个方法#异常类型 exc_type,异常值 exc_val,和异常跟踪信息 exc_tbprint(exc_type, exc_val, exc_tb)self.file_obj.close()
#with File("test.txt") as opened_file:#File中的self.file_obj返回给opened_file#opened_file.write("Hiiii")#opened_file.read() #只写文件,读会报错#with open("test2.txt", "w") as write_file: #直接实现对文件的修改#write_file.write("hello world")from contextlib import contextmanager
@contextmanager
def open_file(name):f = open(name, "w")try:yield f #这行代码是 contextmanager 装饰器使用的关键。# 它暂停了生成器的执行,并将 f 返回给上下文管理器的调用者。# 调用者可以使用这个文件对象进行读写操作。# 当调用者完成操作并退出 with 语句块时,生成器的执行将继续进行。finally:f.close()
"""
change_file打开了test3文件,文件对象返回给变量f
然后执行try命令,遇见yield f,暂停并返回给with语句调用者。
执行with语句中的操作,执行完毕后,生成器将继续执行。
"""
#with open_file("test3.txt") as f:#f.write("Context\n")#实现一个简单的性能监控装饰器
import functools
import time
import tracemallocdef performance(func):@functools.wraps(func)def wrapper_time_memory(*args, **kwargs):start_time = time.time()tracemalloc.start()value = func(*args,**kwargs)snapshot = tracemalloc.get_traced_memory()tracemalloc.stop()# 分别获取当前内存和峰值内存current_memory = snapshot[0]peak_memory = snapshot[1]end_time = time.time()time_taken = end_time - start_timeprint(f"Time: {time_taken:.4f} seconds") #格式化输出时间print(f"Memory taken: {current_memory/1024:.2f} KB")print(f"Peak Memory taken: {peak_memory/1024:.2f} KB")return valuereturn wrapper_time_memory@performance
def fibon(n):a=b=1for i in range(n):yield aa,b = b,a+bfibon(100) #运行时打印时间和内存占用情况
for i in fibon(100): #生成器会再次运行,再打印一次print(i)

遇见的挑战难及解决方法和笔记点见注释。

The challenges encountered, solutions, and key points for note-taking are indicated in the comments.

Resources Used

  • [Python Tips]: A book of many contents like generators, decorators, mutation and so on.
  • [Real Python]: Primer on Python Decorators.

Tomorrow's Plan

Today's Plan

Personal Thoughts

Today, my learning progress was faster than yesterday. Interestingly, I found that the knowledge is crossed because yesterday I used the classes although I don't have an insight of it. This made me think the tools are just tools, you may not need to know how it was invented before you used them. Of course, it would be better if you got a clear understanding of the tools. I am glad I am on my way.

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

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

相关文章

开源 - Ideal库 - Excel帮助类,设计思路(一)

封装Excel常用操作,围绕导入导出设计,通过DataTable实现对象集合与Excel转换,分为对象集合与DataTable转换、DataTable与Excel转换两部分,最终整合为对象集合与Excel转换方法。今天开始和大家分享关于Excel最长常用操作封装。01、起因 市面上有很多Excel操作库,这些库设计…

C++动态库详解

dmjcb个人博客 原文地址动态库 概念 动态库($Dynamic$ $Library$), 又称动态链接库($Dynamic$ $Link$ $Library$, $DLL$), 是一种在程序运行时所加载文件 其与静态库主要区别在于动态库代码并不在程序编译时直接包含, 而是在程序执行时根据需要动态加载 格式 graph LR;X(格式)X…

数分笔记

符号说明(部分) 存在唯一:\(\exist|\) 或 \(\exist!\) 使得:\(\operatorname{s.t.}\)(so that/such that) 非:\(\neg\) 正整数:\(\mathbb{Z}^+,\mathbb{N}_+,\mathbb{Z}_+,\mathbb{N}^+\) 定义为:\(\triangleq\) 或 \(\dot=\) 笛卡尔乘积 \(A\times B=\{(a,b)|a\in A,…

自用软件推荐、 思源笔记插件 | 记录

效率软件mykeyMap,可以设置键盘快捷键,提高码字效率。小键盘福音。 ​​自用习惯:(超级键Caps组合) 可以设置快捷启动软件 可以快速切换窗口,管理窗口。 可以快速调节音量 可以划词直接搜索其他网站内容(还挺好用的,平时搜索素材不用一个一个地打开网站再复制进去搜索)…

从零开始学 Maven:简化 Java 项目的构建与管理

Maven 是一个由 Apache 软件基金会开发的项目管理和构建自动化工具。它主要用在 Java 项目中,但也可以用于其他类型的项目。一、关于Maven 1.1 简介 Maven 是一个由 Apache 软件基金会开发的项目管理和构建自动化工具。它主要用在 Java 项目中,但也可以用于其他类型的项目。M…

左侧导航栏element -2024/11/27

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>首页</title><style>.demo-table-expand {font-size: 0;}.demo-table-expand label {width: 90px;color: #99a9bf;}.demo-table-expand …

考研打卡(28)

开局(28) 开始时间 2024-11-27 22:50:07 结束时间 2024-11-27 23:25:29明天是1124刚才和室友去吃了一百一的羊肉火锅数据结构 设哈希表长m=14,哈希函数H(key)=key MOD 11。 表中已有4个节点addr(15)=4,addr(38)=5,addr(61)=6,addr(84)=7, 其余地址为空,如用二次探查再散…

ThreeJs-04详解材质与纹理

一.matcap材质 这个材质不会受到光照影响,但是如果图片本身有光就可以一直渲染这个图片本来的样子,用来将一个图片纹理渲染到物体上的材质代码实现 加载模型后,开启纹理渲染,并把它的材质变为这个材质,并且贴上纹理图二.Lambert材质 Lambert网格材质是Three.js中最基本和常…

Java学习笔记——2024.11.27

2024.11.27 一、字符类型 1.字符类型初探可以存放一个汉字(2字节)或者数字(这个c4存储的应该是ASCII编码为97的字符,也就是a)2.字符类型细节public class Chardetial {public static void main(String[] args) {char c1 = 97;System.out.println(c1); // achar c2 = a;System.…

JDBC API

1.DriverManager 1》注册驱动,mysql8以上版本可省 2》连接数据库 2.Connection 1》获取执行sql对象 2》管理事务(统一失败)3.Statement 1》执行sql语句4.ResultSet创建集合 List accounts = new ArrayList<类名>();accounts为集合名 往集合中添加类 accounts.add(类名…

linux模拟HID USB设备及wireshark USB抓包配置

目录1. 内核配置2. 设备配置附 wireshark USB抓包配置 linux下模拟USB HID设备的简单记录,其他USB设备类似。 1. 内核配置 内核启用USB Gadget,使用fs配置usb device信息。 Device Drivers ---> [*] USB support ---><*> USB Gadget Support ---><*…

2024御网杯信息安全大赛个人赛wp_2024-11-27

MISC题解 题目附件以及工具链接: 通过网盘分享的文件:御网杯附件 链接: https://pan.baidu.com/s/1LNA6Xz6eZodSV0Io9jGSZg 提取码: jay1 --来自百度网盘超级会员v1的分享一.信息安全大赛的通知 Ctrl+A发现存在隐写:选中中间空白那一部分,把文字变成红色,得出flag二、编码…