面向对象编程是最有效的软件编写方法之一。在面对对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。
根据类来创建对象被称为实例化。
9.1 创建和使用类
1、创建Dog类
‘’‘
class Dog():
def __init__(self,name,age):
self.name = name
self.age = age
def sit(self):
print(self.name.title()+" is now sitting.")
def roll_over(self):
print(self.name.title()+" rolled over.")
’‘’
根据约定,在Python中,首字母大写的名称指的是类。
类中的函数称为方法。
1.方法__init__()
方法__init__是一个特殊的方法,每当你根据Dog类创建新实例时,Python都会自动调用它。
在这个方法的定义中,形参self必不可少,还必须位于其他形参的前面。因为Python在调用这个__init__()方法创建Dog实例时,将自动传入实参self。每个与类相关联的方法调用都会自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
我们创建Dog实例时,Python将调用Dog类的方法__init__()。我们将通过实参向Dog()传递名字和年龄(例子中定义的其他两个形参);self会自动传递,因此我们不需要传递它。每当我们根据Dog类创建实例时,都只需给最后两个形参(例子中的名字和年龄)提供值。
以self为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。举例:
self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。
像这样可通过实例访问的变量称为属性。
2、根据类创建实例(沿用Dog类做例)
使用实参调用Dog类中的__init__()方法。方法__init__()并未显式的包含return语句,但Python自动返回一个表示这条小狗的实例。
我们通常可以认为首字母大写的名称指的是类,而小写的名称指的是根据类创建的实例。
1、访问属性
要访问实例的属性,可使用句点表示法 。 ---- 举例:my_dog.name
句点表示法在Python中很常见,这种语法演示了Python如何获悉属性的值。在这里,Python先找到实例my_dog,再查找与这个实例相关联的属性name。
2、调用方法
根据Dog类创建实例后,要调用类中的方法,可指定实例的名称(这里是my_dog)和要调用的方法,并用句点分隔它们。 ---- my_dog.sit()
心得:类的括号里写的应该是继承的类,只有函数的括号里填的是形参。
3、创建多个实例
可按需求根据类创建任意数量的实例。
我们可以按需求根据一个类创建任意数量的实例,条件是将每个实例都存储在不同的变量中,或占用列表或字典的不同位置。
9.2 使用类和实例
1、Car类
‘’‘
class Car():
def __init__(self,make,model,year):
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
long_name = self.make+" "+self.model+" "+self.year
return long_name.title()
’‘’
2、给属性指定默认值
类中的每个属性(即self.variable这种类型)都必须有初始值,哪怕这个值是0或者空字符串。如设置了默认值,就无需在__init__()方法内为它提供初始值的形参。
3、修改属性的值
三种方法修改属性的值:直接通过实例修改;通过方法进行设置;通过方法进行递增。
1、直接修改属性的值
使用句点表示法直接访问并设置属性。 ---- 举例:my_new_car.odometer_reading = 33
2、通过方法修改属性的值
对Car类中的修改是添加一个update_odometer()的方法,这个方法接受了一个里程值,并将其存储到self.odometer_reading中。通过调用update_odometer()方法,传递实参,将self.odometer_reading值进行修改。通过在方法中修改属性,还可以进行一些条件设置。
3、通过方法对属性的值进行递增
递增,就是创建一个方法,用+=的方式给属性传递值。
9.3 继承
一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。
1、子类的方法__init__()
创建子类时,父类必须包含在当前文件中,且位于子类前面。
定义子类时,必须在括号内指定父类的名称。
方法__init__()接受创建Car实例所需的信息。
super()是一个特殊函数,帮助Python将父类和子类关联起来,调用父类的方法__init__(),让子类实例包含父类的所有属性。父类也称superclass,super因此得名。
2、在Python2.7中的继承
函数super()需要两个实参:子类名和对象self。
3、给子类定义属性和方法
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。
4、重写父类的方法
对于父类的方法,只要它不符合子类模拟的实物的行为,都可以对其进行重写。
为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。
5、将实例用作属性(有难度)
由于使用代码模拟实物时,可能属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。可以将大型类拆分成多个协同工作的小类。
即将一个大类中的一部分创建成一个小类,大类中的某个属性定义为调用该小类,在大类的实例时,采用句点表示法,调用该属性(实际为调用了该小类)并继续用句点调用该小类中的属性或方法。
6、模拟实物
如何使用代码来表示实物,现实世界的建模方法并没有对错之分,只有效率高低,要找出效率最高的表示法,需要经过一定的实践尝试。
9.4 导入类
为让文件尽可能整洁,Python允许将类存储在模块中,然后在主程序中导入所需要的模块。
1、导入单个类
2、在一个模块中存储多个类
3、从一个模块中导入多个类 ---- from module import Class1,Class2....
4、导入整个模块
还可以导入整个模块,再使用句点表示法访问需要的类。 ----- 使用语法module_name.class_name访问需要的类。
5、导入模块中的所有类 ---- from module_name import *
不推荐这种导入方法:这种导入方法可能引发名称方面的困惑,如果不小心导入了一个与程序文件中其他东西同名的类,会引发诊断错误。
6、在一个模块中导入另一个模块
7、自定义工作流程
一开始应让代码结构尽可能简单。先尽可能在一个文件中完成所有的工作,确定一切都能正确运行后,再将类移到独立的模块中。
9.5 Python标准库
了解标准库的网站Python Module of the Week ---- PyMOTW
9.6 类编码风格
类名应采用驼峰命名法
每个类,都应紧跟在类定义后面包含一个文档字符串,用于简要描述类的功能
使用空行来组织代码。在类中,使用一个空行来分隔方法;在模块中,使用两个空行来分隔类。
同时需要导入标准库模块和自己的模块时,先导入标准库模块,再添加一个空行,然后编写导入自己的模块语句。