You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类__init__方法中参数与非参数变量的差异及疑问

关于Python类中__init__参数与实例属性的区别解析

先看你给出的三段代码:

Block №1

class Car:
    def __init__(self, make, model, year, odometer_reading):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = odometer_reading

Block №2

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

Block №3

class Car:
    def __init__(self, make, model, year, odometer_reading = 0):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = odometer_reading

一、__init__括号内的参数和直接赋值的实例属性的区别

不止是默认值的问题,核心差异在灵活性和初始化逻辑:

  • 当odometer_reading在__init__括号内时(比如Block1),它是必填参数——创建实例时必须传入对应的值,否则会报错。这种方式强制要求初始化时就确定这个属性的值,适合必须在创建时明确的属性。
  • 不在括号内直接赋值(比如Block2),这个属性的初始值是固定死的,创建实例时没法直接传入自定义值,只能在实例创建完成后再修改car.odometer_reading。这种方式适合初始值固定、不需要在创建时自定义的属性。

除此之外还有两点差异:

  1. 参数传递可控性:括号内的参数可以利用Python的位置/关键字参数规则灵活传递,而直接赋值的属性完全由类内部逻辑决定,外部创建时无法干预。
  2. 代码可读性:括号内的参数能直观告诉使用者,这个类初始化时需要哪些数据;直接赋值的属性则隐藏了初始化逻辑,使用者得查看类内部代码才知道存在这个属性。

二、Block №2和Block №3的区别

这两种写法的核心差异是初始化时是否允许自定义属性值:

  • Block2的odometer_reading初始值固定为0,创建实例时你没法在Car()里传入这个值,只能之后手动修改,比如my_car = Car('Toyota', 'Camry', 2023)之后再执行my_car.odometer_reading = 500。
  • Block3的odometer_reading是带默认值的可选参数,创建实例时可选择传值或不传:
    • 不传则用默认值0:my_car = Car('Toyota', 'Camry', 2023)
    • 传值则用你传入的值:my_car = Car('Toyota', 'Camry', 2023, 500) 或者用关键字参数my_car = Car('Toyota', 'Camry', 2023, odometer_reading=500)

另外,Block3的写法更贴合Python"显式优于隐式"的原则,使用者不用看类内部代码,就能知道这个属性可以自定义初始值;而Block2的写法则隐藏了这个可能性。

内容的提问来源于stack exchange,提问作者Malpertui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 17:25:08