Python类型:None和Ellipsis

Python中,None是NoneType类型的唯一全局实例,整个Python程序中只有一个None对象。它是Python官方定义的标准空值,表示 "不存在、未设置、无结果"。

print(None)          # 输出:None
print(type(None))    # 输出:<class 'NoneType'>
print(id(None))      # 固定内存地址,全局唯一

is判断的是内存地址是否相同,因为None是单例,所以x is None永远准确。
==判断的是值是否相等,如果自定义类重写了 __eq__ 方法,可能会返回错误的结果。

判读返回布尔值:

None,NoneType,空值、不存在,False。

"",str,空字符串,False。

[],list,空列表,False。

(),tuple,空元祖,False。

{},dict,空字典,False。

0,int,数字 0,False。

False,bool,布尔假,False。

x=None
y=""
z=()
# 只判断是否是None
if x is None:
    print("x是None.")
if y is None:
    print("y是None.")

# 判断是否是"空值"(None、空字符串、空列表等)
if not x:
    print("x是空的.")
# 判断是否是"空值"(None、空字符串、空列表等)
if not y:
    print("y是空的.")
if not z:
    print("z是空的.")

Ellipsis类型:

...(三个连续的点)被称为 Ellipsis,是唯一全局实例,本身没有任何内置功能,所有含义都是框架或开发者约定俗成的。

# 1. 直接使用 ...
ellipsis_literal = ...

# 2. 通过内置名称
from builtins import Ellipsis
ellipsis_object = Ellipsis

# 3. 验证它们是同一个对象
print(...)                    # 输出: Ellipsis
print(type(...))              # 输出: <class 'ellipsis'>
print(... is Ellipsis)        # 输出: True
print(id(...), id(Ellipsis))  # 相同的ID
## 1、函数参数默认值设为 ...
def hello(id,name=...):
    if name is ...:
        print(f"{id},你没有传入名字!")
    else:
        print(f"{id},Hello {name} !")

hello(1)          # 不传参数,用默认值 ...
hello(2,"张三")

## 2、函数返回 ...
def get_ellipsis():
    return ...

result = get_ellipsis()
print(f"返回值: {result}")
print(f"返回值类型: {type(result)}")
print(f"是不是 Ellipsis: {result is Ellipsis}")

## 3、把...当普通参数传递
def check_value(x):
    if x is ...:
        print("✅ 你传入了省略号 ...")
    else:
        print(f"❌ 你传入了: {x}")
check_value(...)

## 4、函数体占位符
def print_str():
    ...

类型标记Any

Any不是一个值,而是来自typing模块的特殊类型标记,它告诉类型检查器:"这里可以是任何类型,跳过类型检查"。

Any,本质是​动态类型,关闭类型检查。

from typing import Any, List, Dict

def demonstrate_assignment():
    # 场景1: 变量声明
    any_value: Any = "string"
    obj_value: object = "string"
    
    # 场景2: 重新赋值
    any_value = 123  # ✅ 类型检查器: 通过
    any_value = [1, 2, 3]  # ✅ 类型检查器: 通过
    obj_value = 123  # ✅ 类型检查器: 通过
    obj_value = [1, 2, 3]  # ✅ 类型检查器: 通过

    # 场景3: 赋值给严格类型
    int_var: int
    int_var = any_value  # ✅ 类型检查器: 通过(危险!)
    # int_var = obj_value     # ❌ 类型检查器: 报错!object 不能赋给 int

    # 场景4: 从严格类型接收
    def takes_int(x: int) -> None:
        pass
    takes_int(any_value)  # ✅ 类型检查器: 通过(危险!)
    # takes_int(obj_value)    # ❌ 类型检查器: 报错
    return any_value, obj_value

函数形参前带*/带** 

*,打包:把所有多余的位置参数打包成一个元组;解包:把可迭代对象(列表/元组/字符串)拆成一个个位置参数。

**,打包:把所有多余的关键字参数打包成一个字典;解包:把字典拆成一个个关键字参数。

# 正确的 *args 用法(接收位置参数,打包成元组)
def print_tuple(*args):
    print(f"args = {args}")
    print(f"args 的类型 = {type(args)}")
    for arg in args:
        print(arg)

# 正确的 **kwargs 用法(接收关键字参数,打包成字典)
# 注意:函数名不要用 dict,这是内置关键字
def print_dict(**kwargs):
    print(f"kwargs = {kwargs}")
    print(f"kwargs 的类型 = {type(kwargs)}")
    # 关键:遍历字典必须用 .items() 才能同时拿到 key 和 value
    for key, value in kwargs.items():
        print(f"key: {key} = value: {value}")

# 测试调用
print_tuple(1, 2, 3, 4, 5, 6, 7, 8, 9)
print("-" * 30)
print_dict(name="张三", age=20, email="zhangsan@example.com")

print(...)  # 输出:Ellipsis
print(type(...))  # 输出:<class 'ellipsis'>
print(... is Ellipsis)  # 输出:True

闭包与@装饰器语法糖

闭包是一个函数,它带着自己出生时周围变量的快照,即使离开那个环境也能访问那些变量。

闭包的关键特征:函数嵌套函数、能记住外层的变量、外层函数执行完后,变量依然存活。

# 计数器工厂
def make_counter():
    count = 0

    def counter():
        nonlocal count
        count += 1
        return count

    return counter

# 创建两个独立的计数器
counterA = make_counter()
counterB = make_counter()

print(counterA())  # 1
print(counterA())  # 2
print(counterB())  # 1  ← 独立的计数

@装饰器语法糖

装饰器是Python最强大的特性之一,本质是一个接收函数作为参数、返回新函数的闭包。

装饰器是「函数的包装器」,在不修改原函数代码的情况下,给它添加新功能。装饰器本质上是高阶函数:接受一个函数,返回一个新函数。

@就是装饰器的语法糖,它让装饰器的使用更优雅。

# 1. 定义装饰器(就是一个普通函数)
def hello_decorator(func):
    # 2. 定义内部函数(包装原函数)
    def wrapper():
        print("装饰器:函数执行前~")
        # 3. 执行原来的函数
        func()
        print("装饰器:函数执行后~")
    # 4. 返回内部函数
    return wrapper

# 5. 使用装饰器(@符号就是语法糖)
@hello_decorator
def say_hello():
    print("Hello World!")

# 6. 调用被装饰后的函数
say_hello()

更多推荐