











记录时间:2026年8月6日
环境:Fedora 44 + Python 3.12.13 + Django 5.2.16
今天的问题层级明显"升维"了 —— 不再局限于 Django,而是直击 Python 语言本身的设计哲学。
问题清单:
__init__()?*args / **kwargs 吗?self / cls 是 Python 关键字吗?每一个问题,都在把"会用"推向"懂原理"。
"如果没有父类,是不是这个类必须要写
__init__()?"
不需要。 即使没有任何显式父类,类也可以不写 __init__()。
Python 3 中,所有类隐式继承自 object:
class Foo: # 等价于 class Foo(object):
pass
object 已经提供了默认的 __init__():
class object:
def __init__(self):
pass # 什么也不做
| 场景 | 示例 |
|---|---|
| 纯工具类(只有静态方法) | MathUtils.add(a, b) |
| 属性在别处动态添加 | t = Temp(); t.x = 10 |
| 继承体系已满足需求 | class MyView(View): pass |
| 场景 | 原因 |
|---|---|
| 需要初始化实例属性 | self.name = name |
| 需要校验参数 | if age < 0: raise ValueError |
| 需要组合其他对象 | self.items = [] |
class A:
pass
class B(A):
pass
b = B() # MRO: B → A → object → object.__init__()
✅ 无论怎么写,最终都会落到 object.__init__()
"
__init__()不是类的必需品,而是实例状态的初始化器。"
"类后面
()中的参数是按照__init__()中参数顺序传递给属性的么?
是不是也可以用*args, **kwargs传递很多个参数?"
是的。 参数会原封不动地传给 __init__()。
class User:
def __init__(self, name, age):
self.name = name
self.age = age
u = User('张三', 18)
# '张三' → name
# 18 → age
*args 接收任意位置参数class User:
def __init__(self, *args):
self.args = args
u = User('张三', 18, '北京')
# self.args == ('张三', 18, '北京')
✅ 打包成元组,不关心数量,不关心名字
❌ 可读性差
**kwargs 接收任意关键字参数class User:
def __init__(self, **kwargs):
self.name = kwargs.get('name')
self.age = kwargs.get('age')
u = User(name='张三', age=18)
✅ 打包成字典,参数名 = key
*args + **kwargs 组合(Django 最爱)class User:
def __init__(self, name, *args, **kwargs):
self.name = name
self.extra_args = args
self.extra_kwargs = kwargs
u = User('张三', 18, '北京', city='上海', job='dev')
# name = '张三'
# extra_args = (18, '北京')
# extra_kwargs = {'city': '上海', 'job': 'dev'}
class View:
def __init__(self, **kwargs):
self.kwargs = kwargs
super().__init__()
# URLConf 中
RegisterView.as_view(msg='hello')
# → self.kwargs == {'msg': 'hello'}
| 参数类型 | 必须出现在签名中 | 能动态使用 |
|---|---|---|
| 位置参数 | ✅ 是 | ❌ |
*args |
❌ 否 | ✅ |
**kwargs |
❌ 否 | ✅ |
class User:
def __init__(self, **kwargs):
self.name = name # ❌ name 未定义!
✅ 正确:
self.name = kwargs['name']
# 或
self.name = kwargs.get('name')
"参数是原材料,
__init__()是装配线,属性是成品。*args/**kwargs只是收集器,属性必须手动赋值。"
"
self是 Python 关键字么?"
"cls也是不是关键字,也是约定这样用?"
都不是关键字,都是 PEP 8 强制约定的参数名。
import keyword
print('self' in keyword.kwlist) # False
print('cls' in keyword.kwlist) # False
print('class' in keyword.kwlist) # True ← 这才是关键字
cls 不叫 class?因为 class 是关键字,不能做参数名:
@classmethod
def as_view(class): # ❌ SyntaxError
pass
所以社区选了 cls(class 的缩写)。
class User:
def greet(this): # ✅ 语法合法
print("hello")
@classmethod
def create(klass): # ✅ 语法合法
return klass()
✅ Python 不在乎名字
❌ 社区会在乎(你会被同事打)
"显式优于隐式。"
如果 self 是关键字,Python 就得自动注入实例:
def greet(self): # self 自动注入
Python 选择让你显式写出来,更清晰、更灵活。
| 名字 | 是否关键字 | 约定位置 | 代表 |
|---|---|---|---|
self |
❌ | 实例方法 | 实例本身 |
cls |
❌ | 类方法 | 类本身 |
this |
❌ | (Java/C++ 用) | — |
class |
✅ | 语言保留 | — |
"
self和cls是约定俗成的名字,不是语言赋予的身份。
不是强制的,但比强制的还严格。"
"Python 的构造函数是什么?"
Python 没有"一个"构造函数,而是两个:
| 方法 | 角色 | 是否常重写 |
|---|---|---|
__new__() |
构造器(Constructor)—— 分配内存 | ❌ 极少 |
__init__() |
初始化器(Initializer)—— 设属性 | ✅ 极频繁 |
obj = MyClass(1, 2)
# 内部执行:
# ① MyClass.__new__(MyClass, 1, 2) → 创建空对象
# ② obj.__init__(1, 2) → 填充属性
# ③ return obj
class Demo:
def __new__(cls, *args, **kwargs):
print("1. __new__ 被调用")
return super().__new__(cls)
def __init__(self, *args, **kwargs):
print("2. __init__ 被调用")
d = Demo()
# 输出:
# 1. __new__ 被调用
# 2. __init__ 被调用
__new__class PositiveInt(int):
def __new__(cls, value):
return super().__new__(cls, abs(value))
PositiveInt(-5) # 5
✅ __init__ 改不了不可变对象
✅ 必须在 __new__ 里改
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
✅ 只有 __new__ 能控制"是否创建新对象"
__init__ 的限制class Demo:
def __init__(self):
return 123 # ❌ TypeError: __init__ should return None
✅ __init__ 必须返回 None
✅ 返回值会被 Python 忽略并报错
| 类 | 用 __new__ |
用 __init__ |
|---|---|---|
View |
❌ | ✅ self.kwargs = kwargs |
Model |
❌ | ✅ self._state = ModelState() |
Field |
偶尔 | ✅ |
"
__new__负责生,__init__负责养。生在前,养在后。"
"在类方法里面,为什么要创建这个实例,目的是什么?"
类方法 = 工厂,实例 = 产品。工厂的目的就是生产产品。
class RegisterView:
@classmethod
def as_view(cls, **initkwargs):
def view(request):
self = cls(**initkwargs) # 创建逻辑集中在这里
self.setup(request)
return self.dispatch(request)
return view
✅ 创建逻辑只写一次
✅ 调用者(Django)不需要懂
✅ 以后改创建逻辑只改一处
class View:
@classmethod
def as_view(cls):
self = cls() # ← 不一定是 View,是谁调用就创建谁
✅ LoginView.as_view() → 创建 LoginView 实例
✅ 写死 View() 就破坏继承
| 阶段 | 能否创建实例 |
|---|---|
| Django 启动 | ❌ |
| URLConf 加载 | ❌ |
| HTTP 请求到来 | ✅ |
原因:请求没来就没有 request,self.request 无法赋值。
RegisterView.as_view(msg='hi')
# initkwargs = {'msg': 'hi'}
# cls(**initkwargs) → self.kwargs = {'msg': 'hi'}
✅ 类级配置安全注入实例
✅ 调用者不需要关心参数怎么用
| 角色 | 对应 |
|---|---|
| 类 | 🏭 工厂 |
| 类方法 | 🏭 工厂的接单窗口 |
cls() |
🏭 生产线启动 |
| 实例 | 📦 产品 |
| 调用者(Django) | 🧑 客户 |
"类方法存在的意义,是把'创建权'收回到类自己手中。"
class View:
http_method_names = ['get', 'post', 'put', 'delete']
# 类方法:Django 启动时执行
@classmethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
# ① 创建实例(__new__ + __init__)
self = cls(**initkwargs)
# ② 绑定请求
self.setup(request, *args, **kwargs)
# ③ 调度
return self.dispatch(request, *args, **kwargs)
return view
# 构造:保存配置
def __init__(self, **kwargs):
self.kwargs = kwargs
super().__init__()
# 绑定请求到实例
def setup(self, request, *args, **kwargs):
self.request = request
self.args = args
self.kwargs = kwargs # ⚠️ 覆盖了 __init__ 里的 kwargs!
# 按 HTTP 方法分发
def dispatch(self, request, *args, **kwargs):
method = request.method.lower()
if method not in self.http_method_names:
return self.http_method_not_allowed(request)
handler = getattr(self, method)
return handler(request, *args, **kwargs)
def http_method_not_allowed(self, request):
from django.http import HttpResponseNotAllowed
return HttpResponseNotAllowed(self.http_method_names)
def get(self, request, *args, **kwargs):
raise NotImplementedError
def post(self, request, *args, **kwargs):
raise NotImplementedError
# 使用
class RegisterView(View):
def __init__(self, msg=None, **kwargs):
self.msg = msg # ✅ 单独保存,防止被 setup 覆盖
super().__init__(**kwargs)
def get(self, request):
return f"GET - {self.msg}"
def post(self, request):
username = request.POST.get('username')
return f"POST - {username} - {self.msg}"
self 是关键字import keyword
'self' in keyword.kwlist # False → 不是关键字
__init__ 是唯一的构造函数# __new__ 才是真正的构造函数(分配内存)
# __init__ 只是初始化器
# 类方法的核心目的恰恰是创建实例
# 不创建实例,CBV 就永远只是"图纸"
*args/**kwargs 会自动变成属性def __init__(self, **kwargs):
pass
u = User(name='张三')
u.name # ❌ AttributeError
✅ 必须手动赋值:self.name = kwargs['name']
"Python 的优雅不在于隐藏复杂度,而在于把每一步都摊开给你看。
__new__生,__init__养,cls造,self用 —— 没有魔法,只有约定。"
| 知识点 | 掌握程度 |
|---|---|
无父类时 __init__() 非必须(object 兜底) |
✅ |
位置参数 / *args / **kwargs 传递机制 |
✅ |
self / cls 非关键字,是 PEP 8 约定 |
✅ |
__new__ vs __init__ 分工 |
✅ |
| 类方法创建实例的 4 个目的 | ✅ |
| Django View 完整最小实现 | ✅ |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。