《python编程:入门到实践》第九章 类

基于已学过Java的基础上,对一些基础定义省略

目录

基于已学过Java的基础上,对一些基础定义省略

1.1 创建类

1.1.1 方法

1.2 使用类和实例

1.2.1 给属性指定默认值

1.2.2 修改属性的值(2种)

1.3 继承 

1.3.1 子类的__init__()

1.3.2 子类定义属性和方法

1.3.3 重写

1.3.4 将实例用作属性

1.4 导入类


1.1 创建类

根据 Dog 类创建的每个实例都将存储名字和年龄。我们赋予了每条小狗蹲下( sit() )和打滚( roll_over() )的能力:
class Dog():
 """一次模拟小狗的简单尝试"""
 def __init__(self, name, age):
  """初始化属性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!")
注意: 类名应采用驼峰命名法 ,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
1.1.1 方法
类中的函数称为方法。

方法__init__()
方法 __init__() 是一个特殊的方法,称为构造方法。每当你根据 类创建新实例时, Python 都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免 Python 默认方法与普通方法发生名称冲突。
方法 __init__() 定义成了包含三个形参: self name age 。在这个方法的定义中,形参 self 必不可少,还必须位于其他形参的前面。 因为 Python 调用这个 __init__() 方法来创建 Dog 实例时,将自动传入实参 self 。每个与类相关联的方法调用都自动传递实参 self ,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
我们创建Dog 实例时, Python 将调用 Dog 类的方法 __init__() 。我们将通过实参向 Dog() 传递名字和年龄; self 会自动传递, 因此我们不需要传递它。每当我们根据 Dog 类创建实例时,都只需给最后两个形参( name age )提供值。

下面我们在刚才的Dog类的基础上创建一个表示特定小狗的实例,完整代码如下:
class Dog():
 """一次模拟小狗的简单尝试"""
 def __init__(self, name, age):
  """初始化属性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!")

my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
my_dog.sit()
my_dog.roll_over()
我们让 Python 创建一条名字为 'willie' 、年龄为 6 的小狗。 方法 __init__() 并未显式地包含 return 语句, 但Python 自动返回一个表示这条小狗的实例。我们将这个实例存储在变量 my_dog 中。
在这里,命名约定很有用:我们通常可以认为首字母大写的名称(如 Dog )指的是类,而
小写的名称(如 my_dog )指的是根据类创建的实例。

此外,我们还可以了解到如何访问实例的属性,即通过句点表示法 :

my_dog.name
在这里, Python 先找到实例 my_dog ,再查找与这个实例相关联的属性 name 。在 Dog 类中引用这个属性时,使用的是self.name
我们还了解到如何调用方法。
要调用方法,可指定实例的名称(这里是 my_dog )和要调用的方法,并用句点分隔它们。遇到代码 my_dog.sit() 时, Python 在类 Dog 中查找方法 sit() 并运行其代码,并以同样的方式解读代码 my_dog.roll_over()

1.2 使用类和实例

在上一示例已经展示了类的一般使用,接下来我们丰富一点玩法,给属性来点东西。

1.2.1 给属性指定默认值
类中的每个属性都必须有初始值,哪怕这个值是 0 或空字符串。在有些情况下,如设置默认值时,在方法 __init__() 内指定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。
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 = str(self.year) + ' ' + self.make + ' ' + self.model
  return long_name.title()
 def read_odometer(self):
  """打印一条指出汽车里程的消息"""
  print("This car has " + str(self.odometer_reading) + " miles on it.")

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

我们聚焦于名为odometer_reading 的属性,在方法__init__()中初始值被设置为0.但odometer_reading不应该一直不变为0,所以我们还需要一个修改该属性的值的途径。

1.2.2 修改属性的值(2种)

1、直接修改。

使用句点表示法直接修改属性的值。

my_new_car.odometer_reading = 23

2、通过方法修改

完整代码如下:

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 = str(self.year) + ' ' + self.make + ' ' + self.model
  return long_name.title()
 def read_odometer(self):
  """打印一条指出汽车里程的消息"""
  print("This car has " + str(self.odometer_reading) + " miles on it.")
 def update_odometer(self, mileage):
   """将里程表读数设置为指定的值"""
   self.odometer_reading = mileage

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()

其中,my_new_car.update_odometer(23),我们调用 了update_odometer() ,并向它提供了实参23,方法update_odometer()中self.odometer_reading = mileage将23赋给了self.odometer_reading

注意: 你可以使用类似于上面的方法来控制用户修改属性值(如里程表读数)的方式,但能够访问程序的人都可以通过直接访问属性来将里程表修改为任何值。要确保安全,还需特别注意细节,以及一些必要的基本检查,如里程表不应该允许减少等,大家可以自己改进。

1.3 继承 

家族有继承,类也有。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类 。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

1.3.1 子类的__init__()

上一示例我们创建了一个Car类,现在我们再建一个ElectricCar类,它具备Car类的所有功能。

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 = str(self.year) + ' ' + self.make + ' ' + self.model
  return long_name.title()
 def read_odometer(self):
  print("This car has " + str(self.odometer_reading) + " miles on it.")
 def update_odometer(self, mileage):
  if mileage >= self.odometer_reading:
   self.odometer_reading = mileage
  else:
   print("You can't roll back an odometer!")
 def increment_odometer(self, miles):
  self.odometer_reading += miles
#ElectricCar类继承Car类
class ElectricCar(Car):
 """电动汽车的独特之处"""
 def __init__(self, make, model, year):
  """初始化父类的属性"""
  super().__init__(make, model, year)

my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
创建子类时,父类必须包含在当前文件中,且位于子类前面。定义子类时,必须在括号内指定父类的名称。方法__init__() 接受创建Car 实例所需的信息。
super() 是一个特殊函数,帮助 Python 将父类和子类关联起来。这行代码让 Python 调用 ElectricCar 的父类的方法 __init__() ,让 ElectricCar 实例包含父类的所有属性。父类也称为超类(superclass),名称super因此而得名。
1.3.2 子类定义属性和方法

在上面的ElectricCar类中添加属于电动汽车独有的属性和方法,例如电池容量及相关信息。

完整代码如下:

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 = str(self.year) + ' ' + self.make + ' ' + self.model
  return long_name.title()
 def read_odometer(self):
  print("This car has " + str(self.odometer_reading) + " miles on it.")
 def update_odometer(self, mileage):
  if mileage >= self.odometer_reading:
   self.odometer_reading = mileage
  else:
   print("You can't roll back an odometer!")
 def increment_odometer(self, miles):
  self.odometer_reading += miles

class ElectricCar(Car):
 """Represent aspects of a car, specific to electric vehicles."""
 def __init__(self, make, model, year):
  """
  电动汽车的独特之处
  初始化父类的属性,再初始化电动汽车特有的属性
  """
  super().__init__(make, model, year)
  self.battery_size = 70
 def describe_battery(self):
  """打印一条描述电瓶容量的消息"""
  print("This car has a " + str(self.battery_size) + "-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
我们添加了新属性 self.battery_size ,并设置其初始值(如 70 )。根据 ElectricCar 类创建的所有实例都将包含这个属性,但所有 Car 实例都不包含它。我们还添加了一个名为 describe_battery() 的方法,它打印有关电瓶的信息。
1.3.3 重写
对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样, Python 将不会考虑这 个父类方法,而只关注你在子类中定义的相应方法。
例如,我们假设一个鸟类,并且在鸟类里定义一个方法 叫,而且是 叽叽叫;但我们需要一个子类是鸽子类,鸽子要 咯咯叫,这时我们就可以重写父类中的方法 叫。
重写,顾名思义,就是把方法的具体内容重新写一遍。
def method():#方法名不变
#具体内容根据子类需要重新写过
1.3.4 将实例用作属性
使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。 你可以将大型类拆分成多个协同工作的小类。
例如,不断给 ElectricCar 类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名 为Battery 的类中,并将一个 Battery 实例用作 ElectricCar 类的一个属性:
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 = str(self.year) + ' ' + self.make + ' ' + self.model
  return long_name.title()
 def read_odometer(self):
  print("This car has " + str(self.odometer_reading) + " miles on it.")
 def update_odometer(self, mileage):
  if mileage >= self.odometer_reading:
   self.odometer_reading = mileage
  else:
   print("You can't roll back an odometer!")
 def increment_odometer(self, miles):
  self.odometer_reading += miles

class Battery():
 """一次模拟电动汽车电瓶的简单尝试"""
 def __init__(self, battery_size=70):
  """初始化电瓶的属性"""
  self.battery_size = battery_size
 def describe_battery(self):
  """打印一条描述电瓶容量的消息"""
  print("This car has a " + str(self.battery_size) + "-kWh battery.")
class ElectricCar(Car):
 """电动汽车的独特之处"""
 def __init__(self, make, model, year):
  """
  初始化父类的属性,再初始化电动汽车特有的属性
  """
  super().__init__(make, model, year)
  self.battery = Battery()
     
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
ElectricCar 类中,我们添加了一个名为 self.battery 的属性 。这行代码让 Python 创建一个新的 Battery 实例(由于没有指定尺寸,因此为默认值 70 ),并将该实例存储在属性self.battery 中。每当方法 __init__() 被调用时,都将执行该操作;因此现在每个 ElectricCar 实例都包含一个自动创建的 Battery 实例,并存储在属性self.battery

1.4 导入类

模块是扩展名为 .py 的文件,包含要导入到程序中的代码。

导入类的方法与导入函数的方法一致,通用语法为:

from module_name import class_name

可参考 第八章中的 1.6 将函数存储在模块中:

 《python编程:入门到实践》第八章 函数_橙雨456的博客-CSDN博客icon-default.png?t=N6B9https://blog.csdn.net/qq_73853771/article/details/131939684

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙雨敲代码ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值