专栏名称: 数据STUDIO
点击领取《Python学习手册》,后台回复「福利」获取。『数据STUDIO』专注于数据科学原创文章分享,内容以 Python 为核心语言,涵盖机器学习、数据分析、可视化、MySQL等领域干货知识总结及实战项目。
目录
相关文章推荐
51好读  ›  专栏  ›  数据STUDIO

Python 中千万不要直接返回 None

数据STUDIO  · 公众号  ·  · 2025-03-20 10:30

正文

请到「今天看啥」查看全文



在 Python 中,处理缺失值时直接返回 None 并不是一个好的做法。作为一个初学者,我曾经也经常这样做,但后来我意识到这会导致代码中出现难以调试的错误,并且需要额外的检查来确保程序的正常运行。

例如,假设我们有一个字典,我们想从中获取某个键的值。如果该键不存在,直接返回 None 可能会导致后续代码出现问题,因为 None 并不包含任何有用的信息,而且可能会引发异常。

例如,如果我像这样从字典中获取数据:

user_data = {"name""Kiran""age": 25}
def get_email(user):
    return user.get("email")  # This will return None if key is missing

e = get_email(user_data)
print(e.upper())  #AttributeError: 'NoneType' object has no attribute 'upper'

如你所见,我们的程序崩溃了。为了避免这种情况,我们必须使用 if e is not None 检查。这有点恼人。

我们应该采用一些不同的方法来解决这个问题。

1. 尝试使用默认值

如果键不存在,返回一个默认值,而不是 None

而不是这样做:

def get_username(user):
    if 'name' in user:
        return user['name']
    return None         # This is bad idea

我们可以这么做

def get_username(user):
    return user.get('name'"Guest")  # It will return a default value
    
    
def get_value(data, key, default="Default Value"):
    return data.get(key, default)

value = get_value(my_dict, 'some_key'"Key not found")
print(value)

这将返回一个默认值(GUEST)。这将确保我们的程序在尝试使用结果时不会中断。如果我们想顺利运行程序,最好使用这种方法。

但如果缺失的数据显示了需要立即关注的问题,我们也可以引发异常。我们应该始终选择适合自己需要的方法。

如果你想使用默认值,那么请确保它们在你的上下文中是有意义的。

2. 如果 None 出现意外,我们可以引发异常

如果键不存在是一个异常情况,可以选择抛出异常。

不要这样做

def get_price(product):
    if 'price' in product:
        return product['price']
    return None           #this is bad approach

我们可以这么做

def get_price(product):
    if 'price' not in product:
        raise ValueError("Product must have a price!")
    return product['price']
    

我们也可以明确地提出错误。这将迫使调用者正确处理这种情况。

例如,调用者可以像这样捕获异常并进行相应处理:

try:
    price = get_price(product)
except ValueError as e:
    print(f"Error: {e}")  # This will handle missing price properly

3. 使用 collections.defaultdict

如果你经常需要处理缺失值,可以使用 collections.defaultdict ,它会为不存在的键提供一个默认值。

from collections import defaultdict

my_dict = defaultdict(lambda: "Default Value")
my_dict['existing_key'] = "Some Value"

print(my_dict['existing_key'])  # 输出: Some Value
print(my_dict['non_existing_key'])  # 输出: Default Value

4. 使用 Optional 类型提示

如果在某些情况下需要返回 None ,那么至少我们应该使用类型提示来明确说明。

而不是这样做

def find_user(username):
    ...  # Some logic
    return None  # Hidden None return

我们应该这么做

from typing import Optional
def find_user(username: str) -> Optional[dict]:
    ...  # Some logic
    return None  # Explicitly stated as an optional return type

现在,如果任何开发人员阅读了这个函数,他/她就会在开始时知道他们需要在这里明确处理 “None”情况。

这也有助于静态分析工具和集成开发环境提供适当的提示和警告。

5. 使用自定义封装类

我们还可以将返回值封装在一个明确表示缺失值的类中

例如:

class Missing:
    def __bool__(self):
        return False

MISSING = Missing()

def get_email(user):
    return user.get('email', MISSING)

email = get_email({})

if not email:
    print("No email provided")

我们不必依赖 None, 这种方法会让我们清楚地知道何时缺少一个值。

6. 使用result模式

我们可以为可能失败的函数返回一个结构化的结果......而不是返回None。

例如

from typing import NamedTuple, Union
class Result(NamedTuple):
    success: bool
    value: Union[str, None]

def get_country(user) -> Result:
    if 'country' in user:
        return Result(True, user['country'])
    return Result(False, None)

result = get_country({})
if not result.success:
    print("No country found!")

这种模式可以清楚地说明函数是否成功。

只要这样做......而不是返回 None ......只要使用这种更好的方法。

希望对你有所帮助。


🏴‍☠️宝藏级🏴‍☠️ 原创公众号『 数据STUDIO 』内容超级硬核。公众号以Python为核心语言,垂直于数据科学领域,包括 可戳 👉 Python MySQL 数据分析 数据可视化 机器学习与数据挖掘 爬虫 等,从入门到进阶!

长按👇关注- 数据STUDIO -设为星标,干货速递







请到「今天看啥」查看全文