None和doctoring的秘密

2024-05-24 01:04
文章标签 none 秘密 doctoring

本文主要是介绍None和doctoring的秘密,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

None和doctoring的秘密

用None和docstring来描述默认值会变的参数

有时,我们想把那种不能够提前固定的值,当作关键字参数的默认值。例如,记录日志消息时,默认的时间应该是出发事件的那一刻。所以,如果调用者没有明确指定时间,那么就默认把调用函数的那一刻当成这条日志的记录时间。现在试试下面的这种写法,假定它能让when参数的默认值随着这个函数每次的执行时间而发生变化。

from time import sleep
from datetime import datetimedef log(message, when=datetime.now()):print(f'{when}: {message}')log('Hi there!')
sleep(0.3)
log('Hello again!')>>>
2024-05-23 20:11:10.224560: Hi there!
2024-05-23 20:11:10.224560: Hello again!

为什么会出现上面的情况,两个时间戳一样。因为datetime.now只执行了一次。参数的默认值只会在系统加载这个模块的时候,计算一遍,而不会在每次执行时都重新计算,这通常意味着这些默认值在程序启动后,就已经定下来了。只要包含这段代码的那个模块已经加载进来,那么when参数的默认值就是加载时计算的那个datetime.now(),系统不会重新计算。

要想在Python里实现这种效果,惯用的办法是把参数的默认值设为None,同时在docstring文档里写清楚,这个参数为None时,函数会怎么运作。给函数写实现代码时,要判断该参数是不是None,如果是,就把它改成相应的默认值。

from time import sleep
from datetime import datetimedef log(message, when=None):"""Log a message with a timestamp.:param message:message (str): The message to log.:param when:A datetime object representing the present time to log.:return:"""if when is None:when = datetime.now()print(f'{when}: {message}')

这次,两条日志的时间戳就不同了。

log('Hi there!')
sleep(0.3)
log('Hello again!')
>>>
2024-05-23 20:26:10.020265: Hi there!
2024-05-23 20:26:10.325351: Hello again!

把参数的默认值写成None还有个重要的意义,就是用来表示那种以后可能由调用者修改内容的默认值(例如某个可变的容器)。例如,我们要写一个函数对采用JSON格式编码的数据做解码。如果无法解码,那么就返回调用时所指定的默认结果,假如调用者当时没有明确指定,那就返回空白的字典。

import jsondef decode(data, default={}):try:return json.loads(data)except ValueError:return default

这样的写法与前面datetime.now的例子有着同样的问题。系统只会计算一次的default参数(在加载这个模块的时候),所以每次调用这个函数时,给调用者返回的都是一开始分配的那个字典,这就是相当于凡是以默认值调用这个函数的代码都共用同一份字典。这会使程序出现很奇怪的效果。

foo = decode('bad data')
foo['stuff'] = 15
bar = decode('also bad')
bar['meep'] = 23
print('Foo:', foo)
print('Bar:', bar)>>>
Foo: {'stuff': 15, 'meep': 23}
Bar: {'stuff': 15, 'meep': 23}

我们本意是想让这两次调用操作得到两个不同的空白字典,每个字典都可以分别用来存放不同的键值。但实际上,只要修改其中一个字典,另一个字典的内容就会受到影响。这种错误的根源在于,foo与bar实际上是同一个字典,都等于系统一开始给default参数确定默认值时所分配的那个字典。它们表示的同一个字典对象。

assert foo is bar

解决这个问题,可以把默认值设成None, 并且在docstring文档里说明,函数在这个值为None时会怎么做。

import jsondef decode(data, default=None):"""Load JSOn data from a string.:param data: JSON data to decode.:param default: Value to return if decoding fails.Defaults to an empty dictionary.:return:"""try:return json.loads(data)except ValueError:if default is None:default = {}return default

这样写,再运行刚才那段测试代码,就可以得出预期的结果了。

foo = decode('{"bad": "data"')
foo['stuff'] = 15
bar = decode('also bad')
bar['meep'] = 23
print('Foo:', foo)
print('Bar:', bar)
assert foo is not bar>>>
Foo: {'stuff': 15}
Bar: {'meep': 23}

这个思路不错吧?下面这种写法把when参数标注成可选(Optional)值,并限定其类型为datetime。于是,它的取值就只有两种可能,要么是None, 要么是datetime对象。

from datetime import datetime
from typing import Optionaldef log_typed(message: str, when:Optional[datetime]=None) -> None:"""Log a message with a timestamp.Parameters:message (str): The message to log.when (Optional[datetime]): datetime of when the message occurred.Defaults to the present time. """if when is None:when = datetime.now()print(f'{when}: {message}')

这篇关于None和doctoring的秘密的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/996931

相关文章

Python中的私有属性与方法:解锁面向对象编程的秘密

在Python的广阔世界里,面向对象编程(OOP)是一种强大而灵活的方法论,它帮助我们更好地组织代码、管理状态,并构建可复用的软件组件。而在这个框架内,私有属性与方法则是实现封装的关键机制之一。它们不仅有助于隐藏类内部的具体实现细节,还能保护数据免受外部干扰。今天,让我们一起探索Python中私有属性与方法的魅力所在,了解它们如何在实际开发中发挥重要作用。 引言 随着软件系统变得越来越复杂,维

Matlab_learning_1(set(gcf,'MenuBar','none','Position',[X,Y,Z,W]))

一、首先举个例程: set(gcf,'MenuBar','none','Position',[X,Y,Z,W]);

exec: /opt/FriendlyARM/toolschain/4.4.3/bin/.arm-none-linux-gnueabi-gcc: not found

ubuntu 使用arm-linux-gcc提示,明明工具存在,而且环境变量也设置好了 /opt/FriendlyARM/toolschain/4.4.3/bin//arm-linux-gcc: 15: exec: /opt/FriendlyARM/toolschain/4.4.3/bin/.arm-none-linux-gnueabi-gcc: not found   file /opt/

Python中的函数艺术:解锁高效编程的秘密

引言 在软件开发过程中,重复使用相同的代码段是不可避免的。这不仅增加了代码量,还可能导致维护困难。通过定义函数,我们可以将这些重复代码抽象出来,封装成一个可重用的组件。这样做的好处显而易见:减少了代码冗余、提高了代码的复用性,同时也使得程序结构更加清晰。 此外,在团队协作时,良好的函数设计有助于提高沟通效率。当每个函数都有明确的功能边界时,成员之间可以更轻松地理解和维护彼此的代码。 基础语法

Python中的集合魔法:解锁高效数据处理的秘密

引言 集合是一种不允许重复元素的数据结构,并且其内部元素无序排列。这种特性使得集合在某些场景下表现得极为出色: 去重:快速去除列表或数组中的重复项。交集、并集、差集等运算:用于比较两个或多个集合间的关系,非常适用于权限控制、用户管理等领域。性能优势:相较于列表,集合在查找元素时速度更快,平均时间复杂度为O(1)。 基础语法介绍 创建集合 在Python中创建一个空集合需要使用set()函

BugKu练习记录:小山丘的秘密

题目: hill能有什么秘密呢 bugku{PLGTGBQHM}其中A=1,flag全为小写 hill解密,a=1,所以z=0,字母表为zabcdefghijklmnopqrstuvwxy,根据图片上的棋子数得到对应的字母,分别是abczadefz,用工具解出明文为whatahill,答案为bugku{whatahill}

Error when checking model target: expected activation_2 to have shape (None, 10) but got array with

我遇到了这个问题,因为我在用reshape层后,忘了改我的GT label的尺寸。 reshape最终的输出是10长度的,但是标签用的还是1长度的 就是(0,0,1,0,0,0,0,...)与3的不匹配

探索Python数据持久化的秘密:ZODB库的神奇之旅

文章目录 探索Python数据持久化的秘密:ZODB库的神奇之旅背景ZODB是什么?如何安装ZODB?简单库函数使用方法场景应用常见Bug及解决方案总结 探索Python数据持久化的秘密:ZODB库的神奇之旅 背景 在Python的广阔世界中,数据持久化是一个不可或缺的需求。无论是为了保存应用程序的状态,还是为了在多个会话之间共享数据,我们都需要一种可靠的方法来存储和

应用层协议(下)Https加密Http的秘密(含逻辑图解 简单易学 通俗易懂!)

绪论​ “如今我努力奔跑,不过是为了追上那个曾经被寄予厚望的自己 —— 约翰丶利文斯顿”,本章承接上章Http,没看过强烈建议看后再看本章,本章主要就是学习Https是干什么的并且去底层的学习Http的原理,将会讲到Https的加密、解密过程。 话不多说安全带系好,发车啦(建议电脑观看)。 Https协议 https也是一个应用层协议,是在http协议的基础上引入了一个加密层

天猫商品详情API:解锁商品收藏与加购信息的秘密

在电商领域的激烈竞争中,准确获取用户的购物行为和偏好成为了商家和开发者提升业务效果的关键。天猫作为中国最大的B2C电商平台之一,其商品详情API接口为商家和开发者提供了强大的数据支持。然而,对于商品收藏与加购信息的获取,由于涉及到用户隐私和商家策略,直接通过API获取这些信息并非易事。本文将探讨如何在遵守天猫平台规则的前提下,间接获取这些关键数据。 一、天猫商品详情API概述 天猫商品详情AP