Python类(class)是创建对象的模板:数据(属性)和操作这些数据的函数(方法)写在一起。按类实例化得到的每个对象,拥有自己的一份属性,方法则通常共用同一套定义。__init__ 负责创建时的初始化,方法的第一个参数 self 指向当前这个对象。

先定义一个类

class 块里写方法。创建对象时传入的参数会进到 __init__,再挂到 self 上。之后通过 对象.方法() 调用:

class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        print(f"{self.name}: 汪汪!")

d = Dog("旺财")
d.bark()

类和对象

类描述这类事物有哪些数据、能做什么,对象则是按这个描述造出来的具体实例。同一个类可以造出很多对象,彼此的属性值可以不同:

class Dog(图纸) 属性:name 方法:bark() 构造:__init__(name) 实例化 实例化 d1 = Dog("旺财") name = 旺财 d2 = Dog("小黑") name = 小黑
类是一张图纸,能照出无数个实例,每个实例有自己的属性(name),方法(bark)共用一份。
d1 = Dog("旺财")
d2 = Dog("小黑")
d1.bark()
d2.bark()

__init__ 构造过程

写成 Dog("旺财") 时,解释器先创建空对象,再自动调用 __init__,并把新对象作为 self 传进去。双下划线包起来的这类方法常被称作特殊方法,由语法触发,而不是你手动去写 d.__init__(...)

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("小明", 20)
print(p.name, p.age)

self 是什么

实例方法的第一个参数约定叫 self,代表调用该方法的那个对象。调用写成 c.increment() 时,不必也不能把 self 再手写进括号,解释器会自动传入:

class Counter:
    def __init__(self):
        self.count = 0

    def increment(self):
        self.count += 1
        return self.count

c = Counter()
print(c.increment())
print(c.increment())

类属性与实例属性

写在类体里、与方法同级的赋值,是类属性,该属所有实例默认共享。写在 __init__ 里、挂在 self 上的,是实例属性,每个对象一份。改某个实例自己的 name 不会改掉别人的 name,但改类属性则可能影响仍在使用该类属性的实例:

class Student:
    school = "第一中学"

    def __init__(self, name):
        self.name = name

s1 = Student("Tom")
s2 = Student("Ann")
print(s1.school, s2.school)
print(s1.name, s2.name)

__str__:打印时的可读表示

默认打印一个对象,往往是类型名加内存地址。__str__ 返回字符串后,print(对象)str(对象) 就会用你给的文本:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"({self.x}, {self.y})"

p = Point(3, 5)
print(p)
print(str(p))

实例方法

方法就是类里的函数,通过 self 读写当前对象的属性。面积、移动、校验,都可以做成方法,让数据和使用方式待在同一处:

Python 类与方法示例运行
class Rectangle:
    def __init__(self, w, h):
        self.w = w
        self.h = h

    def area(self):
        return self.w * self.h

r = Rectangle(4, 5)
print(r.area())

常见误区

  • 实例方法的第一个参数别漏掉 self(名字可改,但必须接收实例)。
  • d.bark 拿到的是绑定方法对象,真正执行要写 d.bark()
  • 每只狗各自的名字这类数据,放实例属性。只有全班共享的常量,才适合类属性。