您的位置:首页 > 编程语言 > Python开发

python -- 类(学习笔记)

2020-08-28 23:16 1081 查看

本文章是对学习python类的内容进行的简单总结

面向对象编程是最有效的软件编写方法之一。在面向对象编程中,我们编写表示现实世界中事务和情景的类,并基于这些类创建。
根据类来创建对象被称为实例化,这让我们能使用类的实例。

1.1 创建和使用类

下面我们来具体创建一些类来演示

1.1.1 创建Dog类

根据Dog类创建的每个实例都将存储名字和年龄。我们赋予了每条小狗蹲下(sit())和打滚(roll——over())的能力。

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中,首字母大写的名称指的是类,这个类定义中的括号是空的,因为我们要从空白创建这个类。
方法_init_:
类中的函数称为方法;_ init_()方法是一个特殊方法,每当我们根据Dog类创建实例时,python都会自动运行它。
在上面例子中我们将方法_init_()定义成包含三个形参:self,name,age。在这个方法的定义中,形参self必不可少,而且要位于其他形参之前,这是因为python调用这个_init_()方法创建实例时,将自动传入实参self。每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能访问类中属性和方法。
我们创建Dog实例时,python将调用Dog类的方法_init_()。我们将通过实参向Dog()传递名字和年龄;self会自动传递,因此我们不需要传递它。
Dog类还定义了另外两个方法:sit()和roll_over()。由于这些方法不需要额外的信息,如名字和年龄,因此它们只有一个形参self。

1.1.2 根据类创建实例

可将类视为有关如何创建实例的说明。Dog类是一系列说明,让Python知道如何创建表示特定小狗的实例。下面来创建一个表示特定小狗的实例:

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!")my_dog=Dog('willie',6)
print("My dog's name is"+my_dog.name.title()+".")
print("My dog is"+str(my_dog.age)+"year old.")
####
My dog's name isWillie.
My dog is 6 year old.

这里使用的是之前编写的Dog类,我们创建一条名字为 ‘wille’ ,年龄为6的小狗。遇到这行代码时,python使用实参 ‘wille’ 和 6调用Dog类中的方法 _ init_()。方法_ init_()创建一个表示特定小狗的实例,并使用我们提供的值来设置属性name和age。方法_ init_()并未显示的包含return语句,但python自动返回一个表示这条小狗的的实例。我们将这个实例存储在变量my_dog中。

调用方法

my_dog.sit()
my_dog.roll_over()
####
Willieis now sitting.
Willierolled over!

创建多个实例

my_dog=Dog('willie',6)
your_dog=Dog('lucy',3)
print("My dog's name is"+my_dog.name.title()+".")
print("My dog is "+str(my_dog.age)+" year old.")
my_dog.sit()
my_dog.roll_over()
print("\nYour dog's name is "+your_dog.name.title()+".")
print("Your dog is "+str(your_dog.age)+"years old.")
your_dog.sit()
your_dog.roll_over()
####
My dog's name isWillie.
My dog is 6 year old.
Willieis now sitting.
Willierolled over!

Your dog's name is Lucy.
Your dog is 3years old.
Lucyis now sitting.
Lucyrolled over!

在这里我们创建了两条小狗,分别命名为willie和lucy。每条小狗都是一个独立的实例,有自己的一组属性。

使用类和实例

我们可以用类来模拟现实世界中的很多情景。类编写好后,我们的大部分时间都将花费在类创建的实例上。我们需要执行的一个重要任务是修改实例的属性。我们可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。

2.1.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=str(self.year)+' '+self.make+' '+self.model
return long_name.title()
my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
####
2016 Audi A4

2.1.2 给属性指定默认值

类中的每个属性都必须有初始值,哪怕这个值是零或者空字符。在有些情况下,如果设置默认值时,在方法_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()
####
2016 Audi A4
This car has 0 miles on it.

上面程序中添加了一个名为odometer_reading的属性,其初始值总是为0.我们还添加了一个名为read_odometer()方法,用于读取汽车的里程表。

2.1.3 修改属性的值

可以以三种不同的方式修改属性的值:直接通过实例进行修改;通过方法进行设置;通过方法进行设置;通过方法进行递增(增加特定的值)。

1.直接修改属性的值

my_new_car.odometer_reading=23
my_new_car.read_odometer()
####
This car has 23 miles on it.

2.通过方法修改属性的值

class Car():
--snip--
def update_odometer(self,mileage):
if mileage >=self.odometer_reading:
self.odometer_reading=mileage
else:
print("You can't roll back an odometer!")

我们新增的update_odometer()会在修改属性前检查指定的读书是否合理。

3.通过方法对属性的值进行递增

class Car():
--snip--
def update_odometer(self,mileage):
--snip--
def increment_odometer(self,miles):
self.odometer_reading += miles

my_new_car=Car('subaru','outback',2013)
print(my_new_car.get_descriptive_name())

my_new_car.update_odometer(23500)
my_new_car.read_odometer()

my_new_car.increment_odometer(100)
my_new_car.read_odometer()
####
2013 Subaru Outback
This car has 23500 miles on it.
This car has 23600 miles on it.

新增的方法increment_odometer()接受一个单位为英里的数字,并将其加入到self.odometer_reading中。

继承

编写类时,并非总是要从空白开始。如果我们要编写的类时另一个现成类的特殊版本,可以考虑使用继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新的类称为子类。子类继承其父类的所有属性和方法,同时还可以定义自己属性和方法。

3.1.1 子类的方法_init_()

下面,我们在前面创建的Car类的基础上创建新类ElectricCar,这样我们只需要为电动汽车特有的属性和行为编写代码。

class Car():
--snip--
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())
####
2016 Tesla Model S

super()是一个特殊函数,帮助python将父类和子类关联起来。这行代码让python调用ElectricCa的父类的方法_init_()。

3.1.2 给子类定义属性和方法

下面我们来添加一个电动车特有属性(电瓶),以及一个描述该属性的方法。我们将存储电瓶容量,并且编写一个打印电瓶描述的方法:

class Car():
--snip--
class ElectricCar(Car):
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()
####
2016 Tesla Model S
This car has a 70-kWh battery.

3.1.3 重写父类的方法

对于父类的方法,只要它有不符合子类模拟的实物的行为,都可以对其进行重写。为此,可以在子类中定义一个这样的方法,即它要与重写的父类方法同名。这样,python将只会关注我们在子类中定义的相应方法。

3.1.4 将实例用作属性

使用代码模拟实物时,我们可能会发现给类添加的细节越来越多:属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。我们可以将大类拆分成多个协同工作的小类。
例如,不断给ElectricCar类添加细节时,我们可能会发现其中包含很多专门针对汽车电脑电瓶的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为Battery的类中,并将一个Battery实例用作ElectricCar类的一个属性:

class Car():
--snip--
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()
####
2016 Tesla Model S
This car has a 70-kWh battery.

上面的代码看似做了很多额外的工作,但好处是现在我们多详细描述电瓶都可以,切不会导致ElectricCa类混乱不堪。下面我们继续给Battery类添加一个方法,它根据电瓶容量报告汽车的续航里程:

class Car():
--snip--
class Battery():
--snip--

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):
--snip--
my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
####
2016 Tesla Model S
This car has a 70-kWh battery.
This car can go approximately 240miles on a full charge.

导入类

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

4.1.1 导入单个类

我们可以创建一个只包含Car类的模块,我们可以将这个模块命名为car.py。然后我们可以新创建其他文件,并在其中导入我们创建好的Car模块。
例如,我们创建新文件new_car:

from car import Car
my_new_car=Car('auid','a4',2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading =23
my_new_car.read_odometer()

第一句处的import语句让python打开模块car,并导入其中的Car类,这样我们就可以使用Car类了。

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

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

from car import Car,ElectriCar

4.1.4 导入整个模块

import car

4.1.5 导入模块中所有类

from module_name import *
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: