Python编程从入门到实践——第九章

前面的学习内容没有写在CSDN里,学习内容从9.3的习题课程开始

第九章 类

9.3 继承

9.3动手试一试

9-8权限

权限:编写一个名为 Privileges 的类,它只有一个属性——privileges,其中
存储了练习 9-7 所说的字符串列表。将方法 show_privileges()移到这个类中。在 Admin
类中,将一个 Privileges 实例用作其属性。创建一个 Admin 实例,并使用方法
show_privileges()来显示其权限。

class User():
    """用户信息类,用于显示用户信息"""
    def __init__(self,first_name,last_name,user_info):
        """初始化属性"""
        self.first_name=first_name
        self.last_name=last_name
        self.user_info=user_info
    def describe_user(self):
        """打印用户信息"""
        print("姓名:"+self.first_name+self.last_name+"\n用户年龄:"+str(self.user_info))
    def  greet_user(self):
        "打印给用户的问候语"
        print("欢迎您来到我们餐厅,您的信息是")

class Privileges():
    def __init__(self,privileges=["can add post","can delete post","can ban user"]):
        self.priviliges=privileges
    def show_privileges(self):
        print("\nPrivileges")
        for privilege in self.priviliges:
            print("The privilege is"+" "+privilege)

class Admin(User):
    """添加管理员权限"""
    def __init__(self, first_name, last_name, user_info):
        super().__init__(first_name, last_name, user_info)
        self.privileges=Privileges() 

admin=Admin("li","zeyu",36)
admin.greet_user()
admin.describe_user()
admin.privileges.show_privileges()

习题9-9

电瓶升级:在本节最后一个 electric_car.py 版本中,给 Battery 类添加一个名为
upgrade_battery()的方法。这个方法检查电瓶容量,如果它不是 85,就将它设置为 85。
创建一辆电瓶容量为默认值的电动汽车,调用方法 get_range(),然后对电瓶进行升级,
并再次调用 get_range()。你会看到这辆汽车的续航里程增加了。

class Car():
    def __init__(self,make,year,model):
        self.make=make
        self.year=year
        self.model=model
    def describle_info(self):
        long_name=str(self.make)+" "+str(self.year)+" "+str(self.model)
        print(long_name.title())
    def get_descriptive(self):
        """获取里程数"""
        print(self.odometer)
    def update_odometer(self,miliage):
        """指定里程数"""
        if miliage >= self.odometer:
            self.odometer=miliage
        else:
            print("里程数不能回拨")
    def increment(self,add_miles):
        self.odometer+=add_miles
    def fill_gas_tank(self):
            """有油箱"""
            print("\nThis car need a gas tank!")
class Battery():
    def __init__(self,battery_size=70):
        self.battery_size=battery_size
    def get_range(self):
        if self.battery_size==70:
            range=240
        elif self.battery_size==85:
            range=270
        message = "\nThis car can go approximately " + str(range)
        message += " miles on a full charge."
        print(message)
    def upgrade_battery(self):
        if self.battery_size!=85:
            self.battery_size=85
        else:
            print("The battery is already upgraded.")
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")

class Electric_car(Car):
    def __init__(self, make, year, model):
        super().__init__(make, year, model)
        self.battery= Battery()
    def fill_gas_tank(self):
        """电动车没有油箱"""
        print("This car doesn't need a gas tank!")

my_tesla=Electric_car("tesla",2016,"model s")
my_tesla.describle_info()
my_tesla.fill_gas_tank()
my_tesla.battery.get_range()
my_tesla.battery.upgrade_battery()
my_tesla.battery.get_range()

一直报错显示:AttributeError: 'Battery' object has no attribute 'battery_size',错误原因主要在于这一行代码

    def _init_(self,battery_size=70):

修正后的代码如下:

    def __init__(self,battery_size=70):

两根下划线呀,这个错误对于新手来说很隐蔽

9.4 导入类

Python允许你将类存储在模块中,然后在主程序中导入所需的模块。

9.4.1 导入单个类

应为自己创建的每个模块都编写文档字符串,用来说明模块文档

"""一个可用于表示汽车的类"""

把所有和车相关的方法写在car类里面,单个的实例出来

创建另一个文件——my_car.py,在其中导入Car类并创建其实例

from car import Car

my_new_car=("aodi","model s",2013)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading=23
my_new_car.read_odometer()

运行后发现报错,显示

Traceback (most recent call last):
  File "c:\workspace\pywork\my_car", line 4, in <module>
    print(my_new_car.get_descriptive_name())
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'tuple' object has no attribute 'get_descriptive_name'

查阅纠正后发现,下面这行代码有错误

my_new_car=("aodi","model s",2013)

在实例化的过程中,没有正确创建实例,实例化的格式应该为

实例名称=类名(属性)

所以修正的代码为

my_new_car=Car("aodi","model s",2013)

输出结果为:

 通过将这个类移到一个模块中,并导入该模块,你依然可以使用其所有功能,但主程序文件变得整洁而易于阅读了。

9.4.2 在一个模块中存储多个类

虽然同一个模块中的类之间应存在某种相关性,但可根据需要在一个模块中存储任意数量的类。
类Battery和ElectricCar都可帮助模拟汽车,因此下面将它们都加入模块car.py中。

class Car():
-snip-
class Battery():
    
    """一次模拟电动汽车电瓶的简单尝试"""
    def __init__(self, battery_size=60):
        """初始化电瓶的属性"""
        self.battery_size = battery_size
        
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")
        
    def get_range(self):
        """打印一条描述电瓶续航里程的消息"""
        if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:
            range = 270
        message = " This car can go approximately " + str(range)
        message += " miles on a full charge."
        print(message)
    
class ElectricCar(Car):
    
    """模拟电动汽车的独特之处"""
    def __init__(self, make, model, year):
        """
        初始化父类的属性,再初始化电动汽车特有的属性
        """
        super().__init__(make, model, year)
        self.battery = Battery()

我按照要求加进去之后,一直报错,报错内容为

 找了很久,终于找到了报错原因,range的值是根据battery_size的变量给的,只有当battery_size=70或者battery_size=85的时候,才会给range变量赋值。

if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:
            range = 270

可是我根据教材上写的内容复制过去,发现battery_size的值=60,不满足条件语句的条件

class Battery():
    
    """一次模拟电动汽车电瓶的简单尝试"""
    def __init__(self, battery_size=60):
        """初始化电瓶的属性"""
        self.battery_size = battery_size

因此也当然不会给range赋值了,将battery_size的初始值改为70就可以正常运行了。

9.4.3 从一个模块中导入多个类

从一个模块中导入多个类时,用逗号分隔了各个类。导入必要的类后,就可根据需要
创建每个类的任意数量的实例。

from car import Car,ElectricCar

my_beetle=ElectricCar("volkswagen","beetle",2016)
print(my_beetle.get_descriptive_name())

my_new_car=Car("aodi","model s",2013)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading=23
my_new_car.read_odometer()

输出结果

9.4.4 导入整个模块

 还可以导入整个模块,再使用句点表示法访问需要的类。这种导入方法很简单,代码也易
于阅读。

由于创建类实例的代码都包含模块名,因此不会与当前文件使用的任何名称发生冲突

import car

my_beetle=car.ElectricCar("volkswagen","beetle",2016)
print(my_beetle.get_descriptive_name())

my_new_car=car.Car("aodi","model s",2013)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading=23
my_new_car.read_odometer()

9.4.5 导入模块中的所有类


要导入模块中的每个类,可使用下面的语法:

from module_name import *

不推荐使用这种导入方式,这种导入方式没有明确地指出你使用了模块中的哪些类。这种导入方式还可能引发名称方面的困惑。如果你不小心导入了一个与程序文件中其他东西同名的类,将引发难以诊断的错误。

需要从一个模块中导入很多类时,最好导入整个模块,并使用module_name.class_name语法
来访问类。这样做时,虽然文件开头并没有列出用到的所有类,但你清楚地知道在程序的哪些地
方使用了导入的模块;你还避免了导入模块中的每个类可能引发的名称冲突。

9.4.6 在一个模块中导入另一个模块

有时候,需要将类分散到多个模块中,以免模块太大,或在同一个模块中存储不相关的类。
将类存储在多个模块中时,你可能会发现一个模块中的类依赖于另一个模块中的类。在这种情况
下,可在前一个模块中导入必要的类。
将Car类存储在一个模块中,并将ElectricCar和Battery类存储在另一个模块中。

将第二个模块命名为electric_car.py(这将覆盖前面创建的文件electric_car.py),并将Battery和ElectricCar类复制到这个模块中:

现在可以分别从每个模块中导入类,以根据需要创建任何类型的汽车了:

 输出结果

 9.4.7 自定义工作流程

如果你喜欢模块和文件的交互方式,可在项目开始时就尝试将类存储到模块中。先找出让你能够编写出可行代码的方式,再尝试让代码更为组织有序。

9.4动手试一试

9-10导入 Restaurant 类

将最新的 Restaurant 类存储在一个模块中。在另一个文件中,导入 Restaurant 类,创建一个 Restaurant 实例,并调用 Restaurant 的一个方法,以确认 import 语句正确无误。

import restaurant

my_first_restaurant=restaurant.Resturant("李泽宇的小店","中国餐厅")
my_first_restaurant.open_restaurant()

运行结果如下:

9-11 导入 Admin 类

以为完成练习 9-8 而做的工作为基础,将 User、 Privileges 和Admin 类存储在一个模块中,再创建一个文件,在其中创建一个 Admin 实例并对其调用方法 show_privileges(),以确认一切都能正确地运行。

user.py

"""一个可用于表示汽车的类"""
class User():
    """用户信息类,用于显示用户信息"""
    def __init__(self,first_name,last_name,user_info):
        """初始化属性"""
        self.first_name=first_name
        self.last_name=last_name
        self.user_info=user_info
    def describe_user(self):
        """打印用户信息"""
        print("姓名:"+self.first_name+self.last_name+"\n用户年龄:"+str(self.user_info))
    def  greet_user(self):
        "打印给用户的问候语"
        print("欢迎您来到我们餐厅,您的信息是")

class Privileges():
    def __init__(self,privileges=["can add post","can delete post","can ban user"]):
        self.priviliges=privileges
    def show_privileges(self):
        print("\nPrivileges")
        for privilege in self.priviliges:
            print("The privilege is"+" "+privilege)

class Admin(User):
    """添加管理员权限"""
    def __init__(self, first_name, last_name, user_info):
        super().__init__(first_name, last_name, user_info)
        self.privileges=Privileges() 

my_user.py

import user

admin=user.Admin("李","泽宇",18)
admin.privileges.show_privileges()

运行结果如下:

 9-12 多个模块

将 User 类存储在一个模块中,并将 Privileges 和 Admin 类存储在另一个模块中。再创建一个文件,在其中创建一个 Admin 实例,并对其调用方法show_privileges(),以确认一切都依然能够正确地运行。

user.py

"""一个可用于表示汽车的类"""
class User():
    """用户信息类,用于显示用户信息"""
    def __init__(self,first_name,last_name,user_info):
        """初始化属性"""
        self.first_name=first_name
        self.last_name=last_name
        self.user_info=user_info
    def describe_user(self):
        """打印用户信息"""
        print("姓名:"+self.first_name+self.last_name+"\n用户年龄:"+str(self.user_info))
    def  greet_user(self):
        "打印给用户的问候语"
        print("欢迎您来到我们餐厅,您的信息是")

privileges.py

from user import User

class Privileges():
    def __init__(self,privileges=["can add post","can delete post","can ban user"]):
        self.priviliges=privileges
    def show_privileges(self):
        print("\nPrivileges")
        for privilege in self.priviliges:
            print("The privilege is"+" "+privilege)

class Admin(User):
    """添加管理员权限"""
    def __init__(self, first_name, last_name, user_info):
        super().__init__(first_name, last_name, user_info)
        self.privileges=Privileges() 

my_user.py

import privileges

admin=privileges.Admin("李","泽宇",18)
admin.privileges.show_privileges()

输出结果

9.5 Python 标准库

 字典让你能够将信息关联起来,但它们不记录你添加键—值对的顺序。要创建字典并记录其
中的键—值对的添加顺序,可使用模块collections中的OrderedDict类。

from collections import OrderedDict

favorite_languages = OrderedDict()

favorite_languages['jen']='python'
favorite_languages['zeyu']='C#'
favorite_languages['yanqing']='C++'
favorite_languages['Ann']='Java'

for name,language in favorite_languages.items():
    print(name.title()+"'s favorite language is "+language.title()+'.')

这里是根据类创建了一个实例(python创建实例的方式:实例名称=类名(属性))

 输出结果

 9.5动手试一试

9-13 使用 OrderedDict

在练习 6-4 中,你使用了一个标准字典来表示词汇表。请使用 OrderedDict 类来重写这个程序,并确认输出的顺序与你在字典中添加键—值对的顺序一致。

同上述的示例代码

9-14 骰子

模块 random 包含以各种方式生成随机数的函数,其中的 randint()返回一个位于指定范围内的整数,例如,下面的代码返回一个 1~6 内的整数:
from random import randint
x = randint(1, 6)
请创建一个 Die 类,它包含一个名为 sides 的属性,该属性的默认值为 6。编写一个名为 roll_die()的方法,它打印位于 1 和骰子面数之间的随机数。创建一个 6 面的骰子,再掷 10 次。
创建一个 10 面的骰子和一个 20 面的骰子,并将它们都掷 10 次。
代码如下,但是它一直报错,不知道为什么

from random import randint

class Die():
    """投掷骰子"""
    def __init__(self,sides=6):
        self.sides=sides
        
    def roll_die(self):
        for i in range(1,11):
            x = randint(1,self.sides)
            print(x)

    #实例化类
    die_first = Die(6)
    die_second = Die(10)
    die_third = Die(20)
    #调用实例
    die_first.roll_die()
    die_second.roll_die()
    die_third.roll_die()

报错内容如下:

后面终于发现了问题,是因为实例化写在类外面,我写在了类里面,所以一定要注意格式呀~

正确代码如下:

from random import randint

class Die():
    """投掷骰子"""
    def __init__(self, sides=6):
        self.sides = sides
        
    def roll_die(self):
        for i in range(1, 11):
            x = randint(1, self.sides)
            print(x)

# 实例化类
die_first = Die(6)
die_second = Die(10)
die_third = Die(20)

# 调用实例方法
die_first.roll_die()
die_second.roll_die()
die_third.roll_die()
9-14补充range函数

补充:在Python中,range() 是一个内置函数,用于创建一个代表一个数字序列的范围对象。它通常用于循环,例如在 for 循环中,来生成一系列连续的整数值。

range() 函数有三种不同的用法:

  1. range(stop):生成从0开始到 stop - 1 结束的整数序列。

  2. range(start, stop):生成从 start 开始到 stop - 1 结束的整数序列。

  3. range(start, stop, step):生成从 start 开始到 stop - 1 结束的整数序列,每个数之间的步长为 step

这些参数可以是整数,也可以是可以转换为整数的其他数据类型。range() 返回的对象实际上是一个生成器(generator),它在需要时按需生成值,而不是一次性将所有值都存储在内存中。

9-15 Python Module of the Week

Python 3 Module of the Week — PyMOTW 3

9.6 类编码风格

 类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名
和模块名都采用小写格式,并在单词之间加上下划线。

对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的
功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,
对其中的类可用于做什么进行描述。

可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,
可使用两个空行来分隔类。

需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,再
添加一个空行,然后编写导入你自己编写的模块的import语句。在包含多条import语句的程序中,
这种做法让人更容易明白程序使用的各个模块都来自何方。

9.7 小结

这一章学习了类的创建,修改值、类的继承、类的实例化、类的导入以及导入Python标准库的类


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值