Python类型:None和Ellipsis 类型标记Any 函数形参前带*/带** 闭包与@装饰器语法糖
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()
更多推荐



所有评论(0)