Python学习从0开始——009类
- 一、类
- 3.1最简形式
- 3.2Class 对象
- 3.3实例对象
- 3.4实例变量
- 二、继承
- 2.1最简形式
- 2.2多重继承
- 三、私有变量
- 四、杂项
一、类
3.1最简形式
class ClassName:<statement-1>...<statement-N>
3.2Class 对象
#包含三种属性引用
class MyClass:"""A simple example class"""i = 12345def f(self):return 'hello world'
MyClass.i 和 MyClass.f 就是有效的属性引用,将分别返回一个整数和一个函数对象。 类属性也可以被赋值,因此可以通过赋值来更改 MyClass.i 的值。 doc 也是一个有效的属性,将返回所属类的文档字符串: “A simple example class”。
实例化操作(“调用”类对象)会创建一个空对象。 许多类喜欢创建带有特定初始状态的自定义实例。 为此类定义可能包含一个名为 init() 的特殊方法:
def __init__(self):self.data = []
当一个类定义了 init() 方法时,类的实例化操作会自动为新创建的类实例发起调用 init()。 因此在这个示例中,可以通过以下语句获得一个经初始化的新实例:
x = MyClass()
提供给类实例化运算符的参数将被传递给 init():
>>> class Complex:
... def __init__(self, realpart, imagpart):
... self.r = realpart
... self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)
3.3实例对象
实例对象所能理解的唯一操作是属性引用。 有两种有效的属性名称:数据属性和方法。
#类定义
>>> class MyClass:
... """A simple example class"""
... i = 12345
... def f(self):
... return 'hello world'
... ##实例化
>>> x = MyClass()#属性调用
>>> x.counter = 1
>>> while x.counter < 10:
... x.counter = x.counter * 2
...
>>> print(x.counter)
16
>>> del x.counter
>>> print(x.counter)
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'counter'
#方法
>>> x.f()
'hello world'
另一类实例属性引用称为 方法。 方法是“从属于”对象的函数。实例对象的有效方法名称依赖于其所属的类。 根据定义,一个类中所有是函数对象的属性都是定义了其实例的相应方法。 因此在我们的示例中,x.f() 是有效的方法引用。
3.4实例变量
实例变量用于每个实例的唯一数据,而类变量用于类的所有实例共享的属性和方法:
>>> class Dog:
... kind = 'canine'
... def __init__(self, name):
... self.name = name
...
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind
'canine'
>>> e.kind
'canine'
>>> d.name
'Fido'
>>> e.name
'Buddy'
设置不共享:
>>> class Dog:
... def __init__(self, name):
... self.name = name
... self.tricks = []
... def add_trick(self, trick):
... self.tricks.append(trick)
...
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']
二、继承
2.1最简形式
class DerivedClassName(BaseClassName):<statement-1>...<statement-N>
方法引用将按以下方式解析:搜索相应的类属性,如有必要将按基类继承链逐步向下查找,如果产生了一个函数对象则方法引用就生效。
派生类可能会重写其基类的方法。 因为方法在调用同一对象的其他方法时没有特殊权限,所以基类方法在尝试调用调用同一基类中定义的另一方法时,可能实际上调用是该基类的派生类中定义的方法。
2.2多重继承
class DerivedClassName(Base1, Base2, Base3):<statement-1>...<statement-N>
方法解析顺序会动态改变以支持对 super() 的协同调用。所有多重继承的情况都会显示出一个或更多的菱形关联。
三、私有变量
那种仅限从一个对象内部访问的“私有”实例变量在 Python 中并不存在。
由于存在对于类私有成员的有效使用场景(例如避免名称与子类所定义的名称相冲突),因此存在对此种机制的有限支持,称为名称改写。 任何形式为 __spam 的标识符(至少带有两个前缀下划线,至多一个后缀下划线)的文本将被替换为 _classname__spam,其中 classname 为去除了前缀下划线的当前类名称。 这种改写不考虑标识符的句法位置,只要它出现在类定义内部就会进行。
class Mapping:def __init__(self, iterable):self.items_list = []self.__update(iterable)def update(self, iterable):for item in iterable:self.items_list.append(item)__update = update # private copy of original update() methodclass MappingSubclass(Mapping):def update(self, keys, values):# provides new signature for update()# but does not break __init__()for item in zip(keys, values):self.items_list.append(item)
__update 标识符会在 Mapping 类中被替换为 _Mapping__update,而在 MappingSubclass 类中被替换为 _MappingSubclass__update。
四、杂项
有时会需要使用类似于 Pascal 的“record”或 C 的“struct”这样的数据类型,将一些命名数据项捆绑在一起。 这种情况适合定义一个空类,然后添加属性:
class Employee:passjohn = Employee() john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000