一些说明
如果实例和类中同时出现相同的属性名称,则属性查找会优先考虑实例:
class Warehouse:purpose = '储藏'region = '西边'w2 = Warehouse()w2.region = '东边'print(w2.purpose, w2.region)w1 = Warehouse()print(w1.purpose, w1.region)
运行结果:
储藏 东边储藏 西边
数据属性可以由方法引用,也可以由对象的普通用户(“客户端”)引用。换句话说,类不能用于实现纯抽象数据类型。事实上,Python 中的任何东西都不可能强制执行数据隐藏 —— 这一切都是基于约定的。(另一方面,用 C 编写的 Python 实现可以完全隐藏实现细节,并在必要时控制对对象的访问;这可以由用 C 编写的 Python 扩展使用。)
客户端应该谨慎使用数据属性 —— 客户端可能会对其数据属性进行修改,从而弄乱方法维护的不变量。请注意,只要避免名称冲突,客户端可能会在不影响方法有效性的情况下将自己的数据属性添加到实例对象中 —— 同样,命名约定可以省去很多麻烦。
从方法内部引用数据属性(或其他方法!)没有捷径可走。我发现这实际上增加了方法的可读性:在浏览一个方法时,不会有混淆局部变量和实例变量的机会。
通常,方法的第一个参数称为 self。这只不过是一种约定:self 这个名称对 Python 绝对没有特殊意义。但是,请注意,如果不遵循约定,代码对其他 Python 程序员的可读性可能会降低。
任何作为类属性的函数对象都为该类的实例定义了一个方法。定义的函数体没有必要在类中:将函数对象赋值给类中的局部变量也是可以的,例如:
# 函数定义在类之外def f1(self, x, y):return min(x, x+y)class C:f = f1def g(self):return '你好!'h = g
现在,f, g 和 h 都是类 C 的属性,它们指向函数对象,因此它们都是 C 实例的方法 —— h 与 g 完全等价。请注意,这种做法通常只会使程序的读者感到困惑。
方法可以使用 self 参数的方法属性来调用其他方法:
class Bag:def __init__(self):self.data = []def add(self, x):self.data.append(x)def addtwice(self, x):self.add(x)self.add(x)bag1 = Bag()bag1.add(5)bag1.addtwice(6)print(bag1.data)
运行结果:
[5, 6, 6]
方法可以像普通函数一样引用全局名称。与方法关联的全局作用域是包含其定义的模块。(类永远不会被用作全局作用域。)虽然很少有在方法中使用全局数据的好理由,但全局作用域有许多合法的用途:首先,方法可以使用导入到全局作用域的函数和模块,也可以使用其中定义的函数和类。通常,包含该方法的类本身就是在这个全局作用域中定义的,在后面,我们将发现为什么一个方法想要引用它自己的类的一些很好的理由。
每个值都是一个对象,因此有一个类(也称为其 type)。它被存储为 object.__class__。
官方文档:
https://docs.python.org/3.9/tutorial/classes.html




