在 Python 里,万物都有 id

print(id(42))            # 整数也是对象
print(id("hello"))       # 字符串也是
print(id([1, 2, 3]))     # 列表也是
print(id(print))         # 函数也是
print(id(int))           # 类型本身也是

每个对象都有:

  • 身份(id,内存地址)
  • 类型(type)

类是对象

class Player: pass

print(type(Player))          # <class 'type'>
print(Player.__class__)      # <class 'type'>

类的"类"是 type——这就是元类的伏笔。

函数是对象

def greet(name):
    return f"hi {name}"

print(type(greet))           # <class 'function'>

# 可以赋给变量
f = greet
print(f("WadeLy"))

# 可以放进列表
funcs = [greet, str.upper, len]
for f in funcs:
    print(f("hello"))

# 可以当参数传
def call_twice(fn, x):
    return fn(x), fn(x)

call_twice(greet, "WadeLy")

这条特性是装饰器、回调、函数式编程的基础。

一切对象都有属性

def greet(name):
    """打招呼"""
    return f"hi {name}"

print(greet.__name__)        # 'greet'
print(greet.__doc__)         # '打招呼'
print(greet.__module__)
greet.tag = "social"         # 函数也能加属性!

看一个对象有什么

print(dir("hello"))      # 字符串的所有方法和属性
print(vars(some_obj))    # 对象的 __dict__(实例属性)
help(str)                # 文档

实战意义

理解"一切皆对象"后,下面这些就不再神奇:

  • dict[func] = "标记" 给函数打 tag
  • 把函数列表放进 dict 实现"命令分发"
  • 装饰器 = 接收函数返回函数
  • 类装饰器 = 接收类返回类
# 命令分发模式
def cmd_add(args): ...
def cmd_list(args): ...
def cmd_done(args): ...

COMMANDS = {
    "add": cmd_add,
    "list": cmd_list,
    "done": cmd_done,
}

cmd, *args = sys.argv[1:]
COMMANDS[cmd](args)

下一篇讲函数式工具:map / filter / reduce / lambda。