None和doctoring的秘密

None和doctoring的秘密

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

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

from time import sleep
from datetime import datetime

def 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 datetime

def 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 json

def 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 json

def 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 Optional

def 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}')

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

创建vue工程、Vue项目的目录结构、Vue项目-启动、API风格

环境准备 介绍:create-vue是Vue官方提供的最新的脚手架工具,用于快速生成一个工程化的Vue项目create-vue提供如下功能: 统一的目录结构 本地调试 热部署 单元测试 集成打包依赖环境:NodeJS 安装NodeJS 一、 创建vue工程 npm 类…

以Linux为例了解线程

我最近开了几个专栏,诚信互三! > |||《算法专栏》::刷题教程来自网站《代码随想录》。||| > |||《C专栏》::记录我学习C的经历,看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

IO系列(八) -浅析NIO工作原理

一、简介 现在使用 NIO 的场景越来越多,很多网上的技术框架或多或少的使用 NIO 技术,譬如 Tomcat、Jetty、Netty,学习和掌握 NIO 技术已经不是一个 Java 攻城狮的加分技能,而是一个必备技能。 那什么是 NIO 呢? NIO…

第06章 数据加载、存储与文件格式

以下内容参考自https://github.com/iamseancheney/python_for_data_analysis_2nd_chinese_version/blob/master/%E7%AC%AC05%E7%AB%A0%20pandas%E5%85%A5%E9%97%A8.md 《利用Python进行数据分析第2版》 用以学习和记录。 输入输出通常可以划分为几个大类:读取文本文…

深海奥秘:鳐鱼肽的肌肤之旅

深海,一个神秘又充满生命力的世界,总是带给我们无尽的惊喜。鳐鱼,又被称为“魔鬼鱼”,它的皮肤中含有一种特殊的肽,这种肽不仅分子量适中,易于人体吸收,还具有极高的消化率和生物利用度。来自北…

科技引领乡村振兴新潮流:运用现代信息技术手段,提升农业生产和乡村管理效率,打造智慧化、现代化的美丽乡村

一、引言 随着科技的不断进步,现代信息技术已经渗透到社会的各个领域,成为推动社会发展的重要力量。在乡村振兴战略的背景下,科技的力量同样不容忽视。本文旨在探讨如何运用现代信息技术手段,提升农业生产和乡村管理效率&#xf…

Android软件渲染流程

Android软件渲染流程 一.渲染流程1.VSync信号的监听2.VSync信号触发绘制 二.渲染原理1.画布的获取1.1 渲染缓存的初始化1.2 graphics::Canvas的创建1.3 graphics::Canvas与渲染缓存的绑定1.3.1 SkBitmap的初始化1.3.2 SkiaCanvas与SkBitmap的绑定1.3.3 SkCanvas的创建 2.矩形的…

Transformer系列专题(二)——multi-headed多头注意力机制

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、什么是multi-headed(多头注意力机制)二、multi-headed三、multi-headed结果四、堆叠多层总结 前言 在实践中,当给定相同…

【数据库基础】基本认识数据库--入门引导

文章目录 什么是数据库?主流数据库基本使用安装MySQL连接服务器服务器、数据库、表关系使用案例数据逻辑存储 MySQL架构SQL语句分类什么叫存储引擎 什么是数据库? 数据库是指在磁盘和内存中存储特定结构组织的数据。数据库通常用于存储于某个系统、组织或…

分布式异步框架celery + Redis 安装配置

引入 这里不对web框架做过多说明,到时候在总结一篇 python的常见web框架 django、flask、tornado、sanic、fastapi..各框架区别 - 内部集成功能的多少 django,内部提供了很多组件。 【相对大】flask、tornado、sanic、fastapi… 本身自己功能很少第…

Linux c开发线程锁和条件变量使用

#include <pthread.h> #include <stdio.h> #include <unistd.h>pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond PTHREAD_COND_INITIALIZER;void* thread_function(void* arg) {printf("线程等待唤醒,锁定互斥量...\n");…

【Unitydemo制作】音游制作—排行榜逻辑Json存储

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

查看当前Shell系统环境变量

查看当前Shell系统环境变量 查看命令 env效果 查看Shell变量(系统环境变量自定义变量函数) 命令 set效果 常用系统环境变量 变量名称含义PATH与windows环境变量PATH功能一样&#xff0c;设置命令的搜索路径&#xff0c;以冒号为分割HOME当前用户主目录&#xff1a;/rootSH…

day08-Java常用API

day08——Java常用API 一、今日内容介绍、API概述 各位同学&#xff0c;我们前面已经学习了面向对象编程&#xff0c;使用面向编程这个套路&#xff0c;我们需要自己写类&#xff0c;然后创建对象来解决问题。但是在以后的实际开发中&#xff0c;更多的时候&#xff0c;我们是…

通过 Spring 操作 Redis

要想通过 Java 操作 redis&#xff0c;首先要连接上 redis 服务器&#xff0c;推荐看通过 Java 操作 redis -- 连接 redis 创建项⽬ 勾选 NoSQL 中的 Spring Data Redis 当然, 把 Web 中的 Spring Web 也勾选⼀下.⽅便写接进⾏后续测试. 配置 redis 服务地址 在 application.…

数据库的约束 not null, unique, default, primary key, foreign key, check

约束可以理解成 数据库提供的一种针对数据的合法性进行验证的机制, 在创建表的时候使用 1. 约束类型 NOT NULL - 指示某列不能存储 NULL 值, 表里的这个内容是必填项UNIQUE - 保证某列的每行必须有唯一的值, 不能重复 每次插入/修改时, 都要先触发查询, 如果当前插入/修改的…

mysql存储比特位

一、介绍 二、SQL CREATE TABLE bits_table (id INT PRIMARY KEY AUTO_INCREMENT,bit_value BIGINT UNSIGNED );-- 插入一个 8 位的 BIT 值 INSERT INTO bits_table (bit_value) VALUES (B10101010);-- 查询并格式化输出 SELECT id,bit_value,CONCAT(b, LPAD(BIN(bit_value),…

解决小皮面版搭建php网站数据库连接不了

首先进入mysql bin目录下 并执行cmd mysql -u root -pCREATE USER userlocalhost IDENTIFIED BY pass;GRANT ALL PRIVILEGES ON *.* TO userlocalhost;GRANT SELECT, INSERT, UPDATE ON database_name.* TO xxwlocalhost;FLUSH PRIVILEGES;select host ,user from mysql.user…

pdf文件怎么编辑?分享3个专业的pdf软件!

在数字化时代&#xff0c;PDF文件已成为我们工作、学习中的得力助手。然而&#xff0c;面对需要修改的PDF文件&#xff0c;许多人却感到无从下手。今天&#xff0c;就让我们一起探索如何轻松编辑PDF文件&#xff0c;并介绍几款实用的编辑软件&#xff0c;让你轻松应对各种PDF编…

Linux DAY 6 _systemctl

systemctl命令&#xff0c;通过这个命令控制系统操作 语法&#xff1a;systemctl start | stop | status | enable | disable 服务名 start 启动 stop 关闭 status 查看状态 enable 开启开机自启 disable 关闭开机自启 服务名&#xff1a; NetworkManager 主网络服务 net…