初识类(一)
本章核心笔记:命名类、属性和方法的标准
类名通常是由大写字母开头,这是标准惯例。
数据的属性听起来应当是数据值的名字。
方法应当是对象或者值的行为。
另外一种是:数据值是名词作为名字,方法是动词加对象。
本章主要知识点:
类和实例
方法
创建类
创建实例
访问实例属性
方法调用
创建子类
使用子类
在python2.2版本中,统一了类型(type)和类(class)。什么意思了?
sb = SongBird() print(type(sb)) print(type([])) 结果: <class '__main__.SongBird'> #都是类 <class 'list'>
list本来是一种数据类型,现在都统一成了类。
python中的一切都是类的实例。
1.类和实例
类与实例的关联:类是实例的定义,而实例是真正的实物,它存放了类中定义的对象的具体信息。
class MyNewObjectType(bases): 'define MyNewObjectType class' pass
定义一个类,关键字是class,紧接着是一个类名。随后是定义的类体代码。
新式类和经典类声明的最大不同在于,所有新式类必须继承至少一个父类。参数bases可以是一个(单继承)或多个(多重继承)用于继承的父类。
object是所有类之母,如果你的类没有继承其他任何父类,object将作为默认的父类。它位于所有类继承结构的最上层。
如果你没有直接或间接的子类化一个对象,那么你就定义了一个经典类。
如果你没有指定一个父类,或者如果所子类化的基本类没有父类,这样就是创建了一个经典类。
很多经典类虽然已经过时,但是你仍然会使用它们。
创建一个实例的过程叫实例化,就像下面这样
myFirstObject = MyNewObjectType()
通常对于新建的类我们会给他赋值,因为如果你没有把这个实例保存在变量中,它就没用了,会被自动垃圾回收器回收,因为没有任何引用指向这个实例。
类可以很简单,也可以很复杂。最简单的情况,类仅用作名称空间。
这意味着你把数据保存在变量中,对它们按名称空间进行分组,使得它们处于同样的关系空间中,这种类仅仅作为空间容器。
2.方法
我们改进类的方式之一就是给类添加功能,类的功能有一个更通俗的名字叫做方法。
在python中,方法在类中定义,但只能在类中调用。比如说,list就是一种类,而每创建的一个list表就是它的实例,表的方法在类中定义,比如append,只能在表中调用。
调用一个方法的过程必须只这样的:
(1)定义类(和方法)
(2)创建一个实例
(3)实例调用方法
就像这样:
#定义一个类 class Bird: def __init__(self): self.hungry = True def ear(self): #定义一个方法 if self.hungry : print('Aaaah...') self.hungry = False else: print('No,thanks') #创建一个实例 b = Bird() #调用方法 b.ear()
你可能注意到了self参数,但不知道是啥,说实话我也不懂啊。
它会在所有方法的声明中都存在。self这个参数代表实例对象本身,当你实例调用方法时,由解释器悄悄的传递给方法,所以你不需要自己传递self进来,因为它是自动传入的。
举例说明一下,假如你有一个带两个参数的方法,你只需要传递第二个参数,python会把self作为第一个参数传进来。(实例在调用方法的时候,会把类传递进来,因为类中有方法的定义啊,不然如何调用。)
后面,我们还会介绍一个特殊的方法__init__(),子类化及继承。在实例化的过程中会调用__init__()方法,进行初始化。
3.创建一个类(类定义)
class AddrBookEntry(object): "address book entry class" def __init__(self,nm,ph): #定义构造器 self.name = nm #设置name参数 self.phone = ph #设置phone参数,没有默认参数必须要传参。 print("Created instance for:",self.name) def updatePhone(self,newph): #方法二 self.phone = newph print("Updated phone# for:",self.name)
在AddrBookEntry类的定义中,定义了两个方法:__init__()和updatePhone()。
__init__()在实例化时(也就是创建一个实例)被调用,即,在AddrBookEntry()被调用时,你可以认为实例化是对__init__()的一种隐式调用。
因为传给AddrBookEntry()的参数与__init__()接受到的参数是一样的,除了self,它是自动传递。
回忆一下,当方法在实例中被调用的时候,self是个标志,由解释器自动传入,所以在上面的__init__()中,需要的参数是nm和ph,它们分别表示名字和电话号码。
__init__()在实例化过程中,会设置这两个属性,以便在实例从实例化调用中返回时,这两个属性对程序员时间可见的。
4.创建实例(实例化)
john = AddrBookEntry('John Doe','408-555-1212') jane = AddrBookEntry('Jane Doe','650-555-1212')
这就是实例化的调用,它会自动调用__init__()。self把实例对象自动传入__init__()。然在实例中就可以设置属性了。
在实例化后,其中的参数就被替换掉了。
如果不存在默认参数,那么传给__init__()的两个参数在实例化时是必须的。
5.访问实例属性
print(john) print(john.name) print(john.phone) print(jane.name) print(jane.phone) 结果: <__main__.AddrBookEntry object at 0x0000017FD4CCD978> John Doe 408-555-1212 Jane Doe 650-555-1212
一旦实例被创建,就可以查证在实例化过程中,我们的实例属性是否确实被__init__()设置了
__init__()初始化实际上是属性赋值的过程。
6.方法的调用
john.updatePhone('415-555-1212') print(john.phone) 结果: 415-555-1212
updatePhone()方法至少需要一个参数,当然self不在之内,新的电话号码被更新之后,检查属性,已经失效。
7.创建子类
靠继承来进行子类化是创建和定制新类型的一种方式,新的类将保持已存在类所有的特性,而不会改动原来类的定义。
对于新类类型而言,这个新的子类可以制定只属于它的特定功能,除了与父类或基类的关系之外,子类与通常的类没有什么区别,也可以像一般类一样进行实例化。
class EmplAddrBookEntry(AddrBookEntry): 'Employee Address Book Entry class' #员工地址簿 def __init__(self,nm,ph,id,em): AddrBookEntry.__init__(self,nm,ph)#借用超类的初始化特性,也就是参数的属性,不然你无法调用,因为没有搭建调用的环境。 self.empid = id self.email = em def updateEmail(self,newem): self.email = newem print("Update e-maile address for:",self.name)
上面我们创建了一个子类EmplAddrBookEntry().
在python中,当一个类被派生出来,子类就继承了基类(也叫父类)的属性,上面新定义了__init__()和updateEmail()方法,也继承了updatePhone()方法。
如果需要,每个子类最好定义它自己的构造器,不然,基类的构造器就会被调用,然而,如果子类重新定义了基类的构造器,基类的构造器就不会被调用了。
8.使用子类
print(john) >><__main__.EmplAddrBookEntry object at 0x00000236839BDA58> print(john.phone) #继承了基类的属性 >>408-555-1212 print(john.name) >>John Doe print(john.email) >>john@spam.doc #自己特有的属性 john.updatePhone('415-555-1212') >>Updated phone# for: John Doe #继承基类的方法 print(john.phone) >>415-555-1212 print(john.email) >>john@spam.doc