Python 金融编程第二版(GPT 重译)(四)(2)

简介: Python 金融编程第二版(GPT 重译)(四)

Python 金融编程第二版(GPT 重译)(四)(1)https://developer.aliyun.com/article/1559357


相关性分析

作为如何使用pandas和金融时间序列数据的进一步说明,考虑标准普尔 500 股指数和 VIX 波动率指数的情况。一个事实是,一般情况下,当标准普尔 500 上涨时,VIX 下降,反之亦然。这涉及相关性而不是因果关系。本节展示了如何为标准普尔 500 和 VIX 之间(高度)负相关的事实提供支持性统计证据。⁴

数据

数据集现在包含两个金融时间序列,都在图 8-8 中可视化。

In [44]: # EOD data from Thomson Reuters Eikon Data API
         raw = pd.read_csv('../../source/tr_eikon_eod_data.csv',
                          index_col=0, parse_dates=True)
In [45]: data = raw[['.SPX', '.VIX']]
In [46]: data.tail()
Out[46]:                .SPX   .VIX
         Date
         2017-10-25  2557.15  11.23
         2017-10-26  2560.40  11.30
         2017-10-27  2581.07   9.80
         2017-10-30  2572.83  10.50
         2017-10-31  2575.26  10.18
In [47]: data.plot(subplots=True, figsize=(10, 6));
         # plt.savefig('../../images/ch08/fts_08.png');


图 8-8. S&P 500 和 VIX 时间序列数据(不同的缩放)

当在单个图中绘制(部分)两个时间序列并进行调整缩放时,两个指数之间的负相关的事实通过简单的视觉检查就已经变得明显。

In [48]: data.loc[:'2012-12-31'].plot(secondary_y='.VIX', figsize=(10, 6));
         # plt.savefig('../../images/ch08/fts_09.png');


图 8-9. S&P 500 和 VIX 时间序列数据(相同的缩放)

对数收益率

如上所述,一般的统计分析依赖于收益而不是绝对变化或甚至绝对值。因此,在进行任何进一步分析之前,首先计算对数收益。图 8-10  显示了随时间变化的对数收益的高变异性。对于两个指数都可以发现所谓的波动率集群。总的来说,股票指数波动率高的时期伴随着波动率指数的同样现象。

In [49]: rets = np.log(data / data.shift(1))
In [50]: rets.head()
Out[50]:                 .SPX      .VIX
         Date
         2010-01-04       NaN       NaN
         2010-01-05  0.003111 -0.035038
         2010-01-06  0.000545 -0.009868
         2010-01-07  0.003993 -0.005233
         2010-01-08  0.002878 -0.050024
In [51]: rets.dropna(inplace=True)
In [52]: rets.plot(subplots=True, figsize=(10, 6));
         # plt.savefig('../../images/ch08/fts_10.png');


图 8-10。S&P 500 和 VIX 的对数收益随时间变化

在这种情况下,pandasscatter_matrix()绘图函数非常方便用于可视化。它将两个系列的对数收益相互绘制,可以在对角线上添加直方图或核密度估计器(KDE)(请参见图 8-11)。

In [53]: pd.plotting.scatter_matrix(rets,  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
                                    alpha=0.2,  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
                                    diagonal='hist',  ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png)
                                    hist_kwds={'bins': 35},  ![4](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/4.png)
                                    figsize=(10, 6));
         # plt.savefig('../../images/ch08/fts_11.png');


要绘制的数据集。


点的不透明度参数为alpha


放置在对角线上的内容;这里是列数据的直方图。


这些是要传递给直方图绘图函数的关键字。


图 8-11。S&P 500 和 VIX 的对数收益作为散点矩阵

OLS 回归

通过所有这些准备,普通最小二乘(OLS)回归分析很方便实现。图 8-12 显示了对数收益的散点图和通过点云的线性回归线。斜率明显为负,支持了关于两个指数之间负相关的事实。

In [54]: reg = np.polyfit(rets['.SPX'], rets['.VIX'], deg=1)  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
In [55]: ax = rets.plot(kind='scatter', x='.SPX', y='.VIX', figsize=(10, 6))  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
         ax.plot(rets['.SPX'], np.polyval(reg, rets['.SPX']), 'r', lw=2);  ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png)
         # plt.savefig('../../images/ch08/fts_12.png');


这实现了线性 OLS 回归。


这将对数收益绘制为散点图…


… 添加了线性回归线。


图 8-12。S&P 500 和 VIX 的对数收益作为散点矩阵

相关性

最后,直接考虑相关性度量。考虑到两种度量,一种是考虑完整数据集的静态度量,另一种是显示一定时间内相关性的滚动度量。图 8-13  说明了相关性确实随时间变化,但鉴于参数设置,始终为负。这确实强有力地支持了 S&P 500 和 VIX 指数之间甚至强烈的负相关的事实。

In [56]: rets.corr()  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
Out[56]:           .SPX      .VIX
         .SPX  1.000000 -0.808372
         .VIX -0.808372  1.000000
In [57]: ax = rets['.SPX'].rolling(window=252).corr(
                           rets['.VIX']).plot(figsize=(10, 6))  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
         ax.axhline(rets.corr().iloc[0, 1], c='r');  ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png)
         # plt.savefig('../../images/ch08/fts_13.png');


整个DataFrame的相关矩阵。


这会绘制随时间变化的滚动相关性……


… 并将静态值添加到绘图中作为水平线。


图 8-13. 标普 500 和 VIX 之间的相关性(静态和滚动)

高频数据

本章介绍了使用pandas进行金融时间序列分析。金融时间序列的一个特殊情况是 tick 数据集。坦率地说,它们可以更多或更少地以与本章迄今为止使用的 EOD 数据集相同的方式处理。一般来说,使用pandas导入这些数据集也是相当快的。所使用的数据集包含 17,352 行数据(另见图 8-14)。

In [58]: %%time
         # data from FXCM Forex Capital Markets Ltd.
         tick = pd.read_csv('../../source/fxcm_eur_usd_tick_data.csv',
                              index_col=0, parse_dates=True)
         CPU times: user 23 ms, sys: 3.35 ms, total: 26.4 ms
         Wall time: 25.1 ms
In [59]: tick.info()
         <class 'pandas.core.frame.DataFrame'>
         DatetimeIndex: 17352 entries, 2017-11-10 12:00:00.007000 to 2017-11-10 14:00:00.131000
         Data columns (total 2 columns):
         Bid    17352 non-null float64
         Ask    17352 non-null float64
         dtypes: float64(2)
         memory usage: 406.7 KB
In [60]: tick['Mid'] = tick.mean(axis=1)  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
In [61]: tick['Mid'].plot(figsize=(10, 6));
         # plt.savefig('../../images/ch08/fts_14.png');


计算每一行数据的Mid价格。


图 8-14. 欧元/美元汇率的 tick 数据

处理 tick 数据通常需要对金融时间序列数据进行重新采样。以下代码将 tick 数据重新采样为一分钟的条形数据。例如,这样的数据集(另见图 8-15)用于回测算法交易策略或实施技术分析。

In [62]: tick_resam = tick.resample(rule='1min', label='right').last()
In [63]: tick_resam.head()
Out[63]:                          Bid      Ask       Mid
         2017-11-10 12:01:00  1.16406  1.16407  1.164065
         2017-11-10 12:02:00  1.16396  1.16397  1.163965
         2017-11-10 12:03:00  1.16416  1.16418  1.164170
         2017-11-10 12:04:00  1.16417  1.16417  1.164170
         2017-11-10 12:05:00  1.16425  1.16427  1.164260
In [64]: tick_resam['Mid'].plot(figsize=(10, 6));
         # plt.savefig('../../images/ch08/fts_15.png')


图 8-15. 欧元/美元汇率的一分钟条形数据

结论

本章涉及金融时间序列,可能是金融领域最重要的数据类型pandas是处理这种数据集的强大工具包,不仅可以进行高效的数据分析,而且还可以轻松进行可视化。pandas还有助于从不同来源读取此类数据集,并将此类数据集导出为不同的技术文件格式。这在随后的第九章第九章中进行了说明。

进一步阅读

本章涵盖的主题在书籍形式上有很好的参考资料:

  • McKinney, Wes (2017): Python for Data Analysis. 2nd ed., O’Reilly, 北京等地.
  • VanderPlas, Jake (2016): Python Data Science Handbook. O’Reilly, 北京等地。

¹ 该文件包含了从汤姆森路透 Eikon 数据 API 检索的不同金融工具的每日结束数据(EOD 数据)。

² 其中一个优点是随时间的可加性,这对于简单的百分比变化/回报并不成立。

³ 预见偏见 ——或者,在其最强形式下,完美预见 ——意味着在金融分析的某个点上使用的数据仅在以后才可用。结果可能是“太好了”的结果,例如,在回测交易策略时。

⁴ 其背后的一个推理是,当股指下跌时——例如在危机期间——交易量会上升,因此波动性也会上升。当股指上涨时,投资者通常会保持冷静,并且不怎么有动力进行大量交易。特别是,仅持有多头头寸的投资者会试图进一步跟进趋势。

第九章:输入/输出操作

在有数据之前进行理论推断是一个大错误。

福尔摩斯

作为一般规则,无论是在金融环境中还是在其他任何应用程序领域,大多数数据都存储在硬盘驱动器(HDDs)或其他形式的永久存储设备上,如固态硬盘(SSDs)或混合硬盘驱动器。多年来,存储容量一直在稳步增长,而存储单元的成本(例如,每兆字节)一直在稳步下降。

与此同时,存储数据的容量增长速度远远快于即使是最大型机器中可用的典型随机访问内存(RAM)。这使得不仅需要将数据存储到磁盘上以进行永久存储,而且需要通过将数据从 RAM 交换到磁盘,然后再交换回来来弥补 RAM 不足的情况。

因此,在金融应用程序和数据密集型应用程序中,输入/输出(I/O)操作通常是重要的任务。通常,它们代表了性能关键计算的瓶颈,因为 I/O  操作通常无法将数据快速地从 RAM 移动到 RAM¹,然后再从 RAM 移动到磁盘。从某种意义上说,CPU 经常由于 I/O 操作慢而“饥饿”。

尽管如今的大部分金融和企业分析工作都面临着大数据(例如,PB 级别),但单个分析任务通常使用的数据子集属于中等数据类别。微软研究的一项研究得出了结论:

我们的测量以及其他最近的工作显示,大多数现实世界的分析任务处理的输入量不超过 100GB,但流行的基础设施,如 Hadoop/MapReduce 最初是为 PB 级处理而设计的。

Appuswamy 等人(2013 年)

就频率而言,单个金融分析任务通常处理不超过几 GB 大小的数据,并且这是 Python 及其科学堆栈库(如NumPypandasPyTables)的甜蜜点。这样大小的数据集也可以在内存中进行分析,利用今天的 CPU 和 GPU 通常会获得较高的速度。但是,必须将数据读入 RAM 并将结果写入磁盘,同时确保满足今天的性能要求。

本章涉及以下主题:

“使用 Python 进行基本 I/O”

Python 具有内置函数,可以对任何对象进行序列化并将其存储到磁盘上,然后从磁盘中读取到 RAM 中;除此之外,在处理文本文件和SQL数据库时,Python 也很强大。NumPy还提供了专用函数,用于快速二进制存储和检索ndarray对象。

“使用 pandas 进行 I/O”

pandas库提供了丰富的便利函数和方法,用于读取存储在不同格式中的数据(例如,CSVJSON)并将数据写入不同格式的文件。

“使用 PyTables 进行快速 I/O”

PyTables 使用具有分层数据库结构和二进制存储的 HDF5 标准来实现对大数据集的快速 I/O 操作;速度通常仅受使用的硬件限制。

“TsTables 的 I/O”

TsTables 是一个构建在 PyTables 之上的包,允许快速存储和检索时间序列数据。

Python 的基本 I/O

Python 本身具有多种 I/O 功能,有些针对性能进行了优化,而其他一些则更注重灵活性。然而,总的来说,它们既可以在交互式环境下使用,也可以在生产环境中轻松应用。

将对象写入磁盘

以供以后使用、文档化或与他人共享,有人可能想要将 Python 对象存储在磁盘上。一个选项是使用 pickle 模块。该模块可以序列化大多数 Python 对象。序列化 指的是将对象(层次结构)转换为字节流;反序列化 是相反的操作。

通常情况下,首先进行一些与绘图相关的导入和自定义:

In [1]: from pylab import plt, mpl
        plt.style.use('seaborn')
        mpl.rcParams['font.family'] = 'serif'
        %matplotlib inline

接下来的示例使用(伪)随机数据,这次存储在 list 对象中:

In [2]: import pickle  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
        import numpy as np
        from random import gauss  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
In [3]: a = [gauss(1.5, 2) for i in range(1000000)]  ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png)
In [4]: path = '/Users/yves/Documents/Temp/data/'  ![4](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/4.png)
In [5]: pkl_file = open(path + 'data.pkl', 'wb')  ![5](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/5.png)


从标准库导入 pickle 模块。


导入 gauss 以生成正态分布的随机数。


创建一个更大的 list 对象,并填充随机数。


指定存储数据文件的路径。


以二进制模式打开文件进行写入(wb)。

用于序列化和反序列化 Python 对象的两个主要函数是 pickle.dump()(用于写入对象)和 pickle.load()(用于将对象加载到内存中):

In [6]: %time pickle.dump(a, pkl_file)  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
        CPU times: user 23.4 ms, sys: 10.1 ms, total: 33.5 ms
        Wall time: 31.9 ms
In [7]: pkl_file.close()  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
In [8]: ll $path*  ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png)
        -rw-r--r--  1 yves  staff    9002006 Jan 18 10:05 /Users/yves/Documents/Temp/data/data.pkl
        -rw-r--r--  1 yves  staff  163328824 Jan 18 10:05 /Users/yves/Documents/Temp/data/tstb.h5
In [9]: pkl_file = open(path + 'data.pkl', 'rb')  ![4](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/4.png)
In [10]: %time b = pickle.load(pkl_file)  ![5](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/5.png)
         CPU times: user 28.7 ms, sys: 15.2 ms, total: 43.9 ms
         Wall time: 41.9 ms
In [11]: a[:3]
Out[11]: [3.0804166128701134, -0.6586387748854099, 3.3266248354210206]
In [12]: b[:3]
Out[12]: [3.0804166128701134, -0.6586387748854099, 3.3266248354210206]
In [13]: np.allclose(np.array(a), np.array(b))  ![6](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/6.png)
Out[13]: True


序列化对象 a 并将其保存到文件中。


关闭文件。


显示磁盘上的文件及其大小(Mac/Linux)。


以二进制模式打开文件进行读取(rb)。


从磁盘读取对象并进行反序列化。


ab 转换为 ndarrary 对象,np.allclose() 验证两者包含相同的数据(数字)。

使用 pickle 存储和检索单个对象显然非常简单。那么两个对象呢?

In [14]: pkl_file = open(path + 'data.pkl', 'wb')
In [15]: %time pickle.dump(np.array(a), pkl_file)  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
         CPU times: user 26.6 ms, sys: 11.5 ms, total: 38.1 ms
         Wall time: 36.3 ms
In [16]: %time pickle.dump(np.array(a) ** 2, pkl_file)  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
         CPU times: user 35.3 ms, sys: 12.7 ms, total: 48 ms
         Wall time: 46.8 ms
In [17]: pkl_file.close()
In [18]: ll $path*  ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png)
         -rw-r--r--  1 yves  staff   16000322 Jan 18 10:05 /Users/yves/Documents/Temp/data/data.pkl
         -rw-r--r--  1 yves  staff  163328824 Jan 18 10:05 /Users/yves/Documents/Temp/data/tstb.h5


序列化 andarray 版本并保存。


序列化 a 的平方 ndarray 版本并保存。


文件现在的大小大约是之前的两倍。

那么如何将两个ndarray对象读回内存?

In [19]: pkl_file = open(path + 'data.pkl', 'rb')
In [20]: x = pickle.load(pkl_file)  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
         x[:4]
Out[20]: array([ 3.08041661, -0.65863877,  3.32662484,  0.77225328])
In [21]: y = pickle.load(pkl_file)  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
         y[:4]
Out[21]: array([  9.48896651,   0.43380504,  11.0664328 ,   0.59637513])
In [22]: pkl_file.close(


这检索到了存储的对象第一个


这检索到了存储的对象第二个

很明显,pickle根据先进先出(FIFO)原则存储对象。但这存在一个主要问题:用户事先无法获得关于存储在pickle文件中的内容的元信息。

有时一个有用的解决方法是不存储单个对象,而是存储包含所有其他对象的dict对象:

In [23]: pkl_file = open(path + 'data.pkl', 'wb')
         pickle.dump({'x': x, 'y': y}, pkl_file)  ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png)
         pkl_file.close()
In [24]: pkl_file = open(path + 'data.pkl', 'rb')
         data = pickle.load(pkl_file)  ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png)
         pkl_file.close()
         for key in data.keys():
             print(key, data[key][:4])
         x [ 3.08041661 -0.65863877  3.32662484  0.77225328]
         y [  9.48896651   0.43380504  11.0664328    0.59637513]
In [25]: !rm -f $path*


存储包含两个ndarray对象的dict对象。


检索dict对象。

然而,这种方法要求一次性写入和读取所有对象。考虑到它带来的更高便利性,这可能是一个可以接受的折中方案。


Python 金融编程第二版(GPT 重译)(四)(3)https://developer.aliyun.com/article/1559367

相关文章
|
7天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
7天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
7天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!
|
9天前
|
设计模式 算法 搜索推荐
Python编程中的设计模式:优雅解决复杂问题的钥匙####
本文将探讨Python编程中几种核心设计模式的应用实例与优势,不涉及具体代码示例,而是聚焦于每种模式背后的设计理念、适用场景及其如何促进代码的可维护性和扩展性。通过理解这些设计模式,开发者可以更加高效地构建软件系统,实现代码复用,提升项目质量。 ####
|
8天前
|
机器学习/深度学习 存储 算法
探索Python编程:从基础到高级应用
【10月更文挑战第38天】本文旨在引导读者从Python的基础知识出发,逐渐深入到高级编程概念。通过简明的语言和实际代码示例,我们将一起探索这门语言的魅力和潜力,理解它如何帮助解决现实问题,并启发我们思考编程在现代社会中的作用和意义。
|
8天前
|
机器学习/深度学习 数据挖掘 开发者
Python编程入门:理解基础语法与编写第一个程序
【10月更文挑战第37天】本文旨在为初学者提供Python编程的初步了解,通过简明的语言和直观的例子,引导读者掌握Python的基础语法,并完成一个简单的程序。我们将从变量、数据类型到控制结构,逐步展开讲解,确保即使是编程新手也能轻松跟上。文章末尾附有完整代码示例,供读者参考和实践。
|
9天前
|
人工智能 数据挖掘 程序员
Python编程入门:从零到英雄
【10月更文挑战第37天】本文将引导你走进Python编程的世界,无论你是初学者还是有一定基础的开发者,都能从中受益。我们将从最基础的语法开始讲解,逐步深入到更复杂的主题,如数据结构、面向对象编程和网络编程等。通过本文的学习,你将能够编写出自己的Python程序,实现各种功能。让我们一起踏上Python编程之旅吧!
|
9天前
|
数据采集 机器学习/深度学习 人工智能
Python编程入门:从基础到实战
【10月更文挑战第36天】本文将带你走进Python的世界,从基础语法出发,逐步深入到实际项目应用。我们将一起探索Python的简洁与强大,通过实例学习如何运用Python解决问题。无论你是编程新手还是希望扩展技能的老手,这篇文章都将为你提供有价值的指导和灵感。让我们一起开启Python编程之旅,用代码书写想法,创造可能。
|
11天前
|
设计模式 程序员 数据处理
编程之旅:探索Python中的装饰器
【10月更文挑战第34天】在编程的海洋中,Python这艘航船以其简洁优雅著称。其中,装饰器作为一项高级特性,如同船上的风帆,让代码更加灵活和强大。本文将带你领略装饰器的奥秘,从基础概念到实际应用,一起感受编程之美。
|
10天前
|
分布式计算 并行计算 大数据
Python编程中的高效数据处理技巧
Python编程中的高效数据处理技巧
29 0