注:建议使用“实例对象”的表述而不是“实例”,是因为 Python 中的一切皆为对象,目前来说你只需知道这个概念即可。
不过为了节省版面,使用“实例”的表述也是完全可以的。
注:用一个类来包含抽象事物的属性和方法,这是面向对象的三大特性之一——”封装“
代码保存在 python_work/car.py 文件中
注:这里说新建的是全新类,是因为还有其他创建类的形式,后面我们会给出。
注1:对于 __init__ 方法的方法名来说,实际上是一种规定,因为它是有特殊作用的,如果不加双下划线,Python 将不会自动调用这个方法。
注1:在类中,名称前后都带有双下划线的函数,是特殊的函数,也被称作魔术方法,一般读作 dunder method,dunder 表示“前后双下划线”。
注1:这里“类中的函数称为方法”的表述是没有问题的,因为方法是特殊的函数,你可以称 __init__ 等类方法为函数,但称作方法则更合适和准确,因为方法是与类的实例对象相关联的,而函数不与特定的实例对象相关联。对于一个类方法来说,我们一般会通过其实例来使用它。
注2:类内的方法叫什么,实际上取决于你怎么使用它,这是 Python 中特有的产物,不过目前来说,你不需要太过纠结,只需要大概了解即可,这只是一个称呼而已,不过这下,你应该能理解为什么许多人会混用方法和函数的称呼了吧!
【拓展补充】如果你想要更好地理解函数和方法的异同,则可以参考知名问答网站上对此的一些回答:
https://stackoverflow.com/questions/155609/whats-the-difference-between-a-method-and-a-function
self 的写法只是一个惯例,你完全可以使用其他的写法,比如其他语言的程序员可能会更熟悉 this,但建议大家遵循约定,这样有助于以后的协作。
注:方法体即是“类中函数的函数体”的别称,毕竟我们现在会将类中的函数称为方法。
类的属性可以简单地理解为“有些什么”
注:类的属性可以简单地理解为“有些什么”。
类的属性可以简单地理解为“有些什么”
在这里,命名约定很有用:
通常可以认为首字母大写的名称(如 Dog)指的是类,
而全小写的名称(如 my_dog)指的是根据类创建的实例。
在这个示例中,创建了两条小狗,分别名为Willie 和 Lucy。每条小狗都是一个独立的实例,有自己的一组属性,能够执行相同的操作。
你可以创建属性完全相同的新实例,比如给第二条小狗指定同样的名字和年龄,这个实例看起来没什么不同,但这个实例是 Python 是根据 Dog 类创建另一个新的实例。
odometer reading:里程表读数
扩展 update_odometer() 方法部分略,可参考原书以禁止将里程表读数往回调:
扩展 update_odometer() 方法部分略,可参考原书以禁止将里程表读数往回调:
注:用一个已存在的类作为基础建立的类,是面向对象的三大特性之一——”继承“
类的第二个单词依然用大写字母
类的第二个单词依然用大写字母
类的第二个单词依然用大写字母
ElectricCar 类中可以添加任意的特殊属性或方法,但如果要添加的属性或方法是所有汽车都有的,那应该考虑将其添加进 Car 类。
ElectricCar 类只包含处理电动汽车特有属性和行为的代码。
当重写方法时,不建议改变原有父类的行为逻辑,例如例子中仅仅是对返回描述信息做了补充,让其包含了电动汽车特有的电池容量属性信息。
注:电动汽车可视为汽车的不同形态,当为子类重写方法后,针对实例对象的不同,调用”同名方法“将产生不同的效果,这是面向对象的三大特性之一——”多态“。
这里我们将针对电池这个部分进行拆分
剪切:复制并删除,然后再粘贴(意思就是删除 ElectricCar 类中这个方法的代码,然后粘贴到这里,当然需要把属性名从 battery_size 改为 size)
(原书)注:如果只描述一辆汽车,将 get_range() 方法放在 Battery 类中也许是合适的,但如果要描述一家汽车制造商的整条产品线,也许应该将 get_range() 方法移到 ElectricCar 类中。在这种情况下,get_range() 依然根据电池容量来确定续航里程,但报告的是一款汽车的续航里程。也可以这样做:仍将 get_range() 方法留在Battery 类中,但向它传递一个参数,如 car_model。此时,get_range() 方法可以根据电池容量和汽车型号报告续航里程。
文件的命名也应遵循蛇形命名法
```python
"""一个用来表示汽车的类"""
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回格式规范的描述性信息"""
long_name = f"{self.year} {self.make}" \
f" {self.model}"
return long_name.title()
def read_odometer(self):
"""打印一条指出汽车行驶里程的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
"""将里程表读数设置为指定的值"""
self.odometer_reading = mileage
def increment_odometer(self, miles):
"""让里程表读数增加指定的量"""
self.odometer_reading += miles
```
导入类是一种高效的编程方式。通过将这个类移到一个模块中并导入该模块,依然可使用其所有功能,但主程序文件变得整洁易读了。这还让你能够将大部分逻辑存储在独立的文件中。在确定类能像你希望的那样工作后,就可以不管这些文件,专注于主程序的高级逻辑了。
```python
class Battery:
"""一次模拟电动汽车电池的简单尝试"""
def __init__(self, size=40):
"""初始化电池的属性"""
self.size = size
def describe_battery(self):
"""打印一条描述电池容量的消息"""
print(f"This car has a {self.size}-kWh battery.")
def get_range(self):
"""打印一条消息,指出电池的续航里程"""
if self.size == 40:
range = 150
elif self.size == 65:
range = 225
print(f"This car can go about {range} miles on a full charge.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
self.battery = Battery()
def describe_battery(self):
"""打印一条描述电池容量的消息"""
print(f"This car has a {self.battery_size}-kWh battery.")
def get_descriptive_name(self):
"""返回格式规范的描述性信息"""
return f"{super.get_descriptive_name()}
```
完整代码限于版面略,请参考原书
完整代码限于版面略,请参考原书
由于是随机的,运行的结果不一定相同,记得多运行几次试试哦
注意:random 模块能用来创建众多有趣的项目,不过在创建与安全相关的应用程序时,请不要使用它,建议改用 secrets 等其他模块。
由于是随机的,运行的结果不一定相同,记得多运行几次试试哦
Python 3 Module of the Week:https://pymotw.com/3/
这是一个不错的持续介绍 Python 中外部模块的网站。
当然,别忘了还有一个常量命名法:字母使用全大写,单词之间加上下划线。
另外对于包含多个单词的文件夹,我们一般使用全小写,并在单词之间加上横杠(-)