1. 什么时候加 .,什么时候不加?
核心规则:. 代表“的”。当需要从某个东西(对象/模块/类)里面去拿它的零件(属性或方法)时,就必须用 .。
- 加
. 的情况: - 访问属性/方法:比如
rect.area(获取 rect 的 area)、"hello".upper()(获取字符串的 upper 方法)、math.pi(获取 math 模块里的 pi 常量)。 - 调用实例方法:比如
rect.get_area()(调用 rect 的 get_area 方法)。
- 不加
. 的情况: - 使用独立的全局函数或变量:比如 Python 自带的
print()、len(),或者你自己直接在文件最外层定义的变量和函数。它们不属于任何特定的对象,所以直接用就行。
2. 什么时候加 (),什么时候不加?
核心规则:() 代表“动手执行”。当你希望某个函数或方法立刻开始干活并给你一个结果时,就要加括号;如果你只是想把它的名字记下来或者传给别人,就不加括号。
- 加
() 的情况(立刻执行): - 调用函数/方法:比如
print("你好")、rect.get_area()。哪怕是 @property 装饰的方法,如果它后面有括号(比如 rect.area()),Python 也会尝试去执行它(不过对于 @property,通常不加括号,加了反而会报错,因为它已经被伪装成属性了)。 - 实例化一个类:比如
rect = Rect(800, 200),这里的括号代表“按图纸生产一个实物”。
- 不加
() 的情况(只拿名字/引用): - 把函数当参数传递:比如
button.on_click(handle_click)。这里你只是告诉按钮:“被点击时,请去调用 handle_click 这个函数”,而不是现在就立刻调用它。 - 访问
@property 装饰的方法:比如 rect.area。因为 @property 的作用就是把方法伪装成普通属性,所以访问它时绝对不能加括号。
3. 括号里什么时候加 self,什么时候不加?
核心规则:self 代表“我自己”。在定义实例方法时,Python 规定必须把“我自己”写在第一个位置;但在外面调用时,Python 会自动帮你塞进去,你绝对不能自己画蛇添足。
- 需要写
self 的情况(仅限定义时): - 在
class 内部定义普通方法时:比如 def area(self):。这里的 self 是告诉 Python:“这个方法是需要绑定到具体某个实例上的”。如果你在方法内部想用自己的属性(比如 self.width)或调用自己的其他方法(比如 self.other_func()),都必须带上 self.。
- 不需要写
self 的情况: @property 和普通的实例方法一样,定义时括号里要写 self。@staticmethod 是纯工具函数,跟具体的“我自己”没关系,所以定义时括号里不需要写 self。
- 在类外面调用方法时:比如
rect.area。虽然定义时有 self,但调用时 Python 会自动把 rect 当作 self 传进去,你写了反而会报错(提示参数给多了)。 - 定义
@property、@staticmethod(静态方法)时:
⚡️ 极速避坑对照表
为了方便你记忆,我把这些规则浓缩成了一张表:
| 场景 | 写法示例 | 规则说明 |
|---|
调用 @property 方法 | rect.area | 加点,不加括号。定义时要写 self,调用时不写。 |
| 调用普通实例方法 | rect.get_area() | 加点,加括号。定义时要写 self,调用时不写。 |
| 把函数当参数传递 | func_name | 不加括号。表示只传递函数的地址,不立刻执行。 |
| 定义静态工具方法 | def add(a, b): | 定义时不写 self。它只是一个放在类里的普通函数。 |
| 实例化一个类 | Rect(800, 200) | 加括号。括号里传的是 __init__ 方法里除了 self 以外的参数。 |
一句话总结:用 . 拿东西,用 () 让它干活;定义方法时老实写上 self 代表“我自己”,调用方法时把 self 忘掉交给 Python 自动处理;遇到 @property 就把它当成一个普通的变量(加点、不加括号)去用就好!
class Rect:
def __init__(self, width, height):
self._width = width # 内部变量通常加个下划线,表示它是受保护的
self._height = height
@property
def area(self):
return self._width * self._height
# 这里的 width 必须和下面 setter 的名字保持一致
@property
def width(self):
return self._width
# 固定写法:@刚才的属性名.setter
@width.setter
def width(self, value):
if value < 0:
print("宽度不能为负数!")
return
self._width = value
rect = Rect(800, 200)
print("面积为:", rect.area) # 像访问属性一样获取面积
rect.width = -100 # 触发 setter 里的限制逻辑,打印“宽度不能为负数!”
print("修改后的宽为:", rect.width)
rect.width=2
print("修改后的宽为:", Rect.width)
输出结果:
面积为: 160000
宽度不能为负数!
修改后的宽为: 800
修改后的宽为: <property object at 0x000001EF7D8E9080>