类(python学习)

本文介绍了面向对象编程的基础,包括如何创建和使用Dog和Car类,以及实例化过程。重点讲解了继承概念,展示了如何创建ElectricCar子类重写父类方法,并演示了如何给属性设置默认值。通过电动汽车实例,展示了如何在实际项目中运用这些概念。
摘要由CSDN通过智能技术生成

目录

8.1创建和使用类

8.1.1创建Dog类

8.1.2根据类创建实例

8.2使用类和实例

8.2.1Car类

8.2.2给属性指定默认值

8.2.3修改属性的值

8.3继承

8.3.1子类的方法__init__()

8.3.2重写父类方法

 8.3.3将实例用作属性

8.4导入类

8.5Python标准库

8.5.1定义

8.5.2类编码风格


 

8.1创建和使用类

面向对象编程是最有效的软件编写方式之一。

在编写时,我们定义一大类对象都有通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。

实用类几乎可以模拟任何东西。

8.1.1创建Dog类

创建类方法 :__init__

class Dog:
    """一次模拟小狗的简单尝试"""
    def __init__(self,name,age):
        """初始化属性name和age"""
        self.name=name
        self.age=age
    def sit(self):
        """模拟小狗收到命令时蹲下"""
        print(self.name)
    def roll_over(self):
        """模拟小狗收到命令时打滚"""
        print(self.age)

代码解析:
1.第一行代码定义了一个名为Dog的类。

2.根据约定,在python中,首字母大写的名称指的是类。

3.类定义中没有圆括号,因为要从空白创建这个类。

4.方法__init__()
(1)类中的函数称为方法。

(2)第三行代码处的方法__init__() 是一个特殊方法,每当我们根据Dog类创建新实例时,python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,是为了避免python默认方法与普通方法发生名称冲突。
(请务必确保__init__()的两边都有两个下划线!!!)

(3)我们定义的方法__init__() 包含三个形参:self、name、age。

(4) 在这个方法的定义中,形参self必不可少,而且必须位于其他形参的前面,self是一个指向实例本身的引用,让实例能够访问类中的属性和方法。

(5)代码中的 self.name和self.age都有前缀self。以self为前缀的变量可供类中的所有方法使用,可以通过类的任何实例来访问。

(6)self.name = name 获取与形参name相关联的值,并将其赋给变量name,然后该变量被关联到当前创建的实例。像这样可通过实例访问的变量称为属性。

8.1.2根据类创建实例

创建一个表示特定小狗的实例

class Dog:
   --snip-- #意思是将上面我们定义的Dog类复制过来(手动复制)
my_dog=Dog('while',6)
print(f"my name is {my_dog.name},I'm {my_dog.age} years old.")

代码解析:
1.在Dog类中方法__init__()创建一个表示特定小狗的实例,并使用提供的值来设置属性name和age

2.接下来python返回一个表示这条小狗的实例,而我们将这个实例赋给了my_dog.

3.命名约定通常可认为首字母大写的名称指的是类,而小写的名称指的是根据类创建的实例。
 


(1)访问属性

要访问实例的属性,可使用句点表示法。

如:self.name

(2)调用方法

"""调用方法"""
my_dog=Dog('while',6)
my_dog.sit()
my_dog.roll_over()

8.2使用类和实例

8.2.1Car类

:编写一个表示汽车的类。它存储了有关汽车的信息,还有一个汇总这些信息的方法。

class Car:
    """一次模拟汽车的简单尝试"""
    def __init__(self,make,model,year):
        '''初始化描述汽车的属性'''
        self.make=make
        self.model=model
        self.year=year
    def get_descriptive_name(self):
        '''返回整洁的描述性信息'''
        long_name=f"{self.year} {self.make} {self.model}"
        return long_name.title()
my_new_car=Car('mayi','a2','2022')
print(my_new_car.get_descriptive_name())

2a5d2744b8664f0c90c6bf3aae6230f4.png

和前面的Dog类一样,这个方法的第一个形参为self。该方法还包括三个形参make,model,year.方法__init__()接受这些形参的值,并将它们赋给根据这个类创建的实例的属性。

还在其中定义了一个函数方法

8.2.2给属性指定默认值

创建实例时,有些属性无须通过形参来定义,可在方法__init__()中为其指定默认值。

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

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} {self.model}"
        return long_name.title()
    def read_odometer(self):
        '''打印一条指出汽车里程的消息'''
        print(f"This car has {self.odometer_reading} miles on it.")
my_new_car=Car('mayi','a2',2022)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

ecf3869205ac44fd9eb8d6dcc3d26e16.png

8.2.3修改属性的值

我们能以三种方式修改属性的值:直接修改属性的值、通过方法修改属性的值、通过方法对属性的值进行递增(增加特定的值)

(1)直接修改属性的值

要修改属性的值,最简单的方式是通过实例直接访问它。

:直接将里程表读数设置为23

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} {self.model}"
        return long_name.title()
    def read_odometer(self):
        '''打印一条指出汽车里程的消息'''
        print(f"This car has {self.odometer_reading} miles on it.")
my_new_car=Car('mayi','a2',2022)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
my_new_car.odometer_reading=23
my_new_car.read_odometer()

e32c475004df40f58a562ee2b1037312.png

(2)通过方法修改属性的值

有时候需要直接访问属性,但其他时候需要编写对属性进行更新的方法

如果有方法能替我们更新属性,将非常方便。这样就无须直接访问属性,而可将值传递给方法,由它在内部进行更新。

例:演示一个名为update_odometer()的方法

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} {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
my_new_car=Car('mayi','a2',2022)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(66)
my_new_car.read_odometer()

2f53061d876d46f5b6de4f6adc9bdec9.png

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

有时候需要讲属性值递增特定的量,而不是将其设置为全新的值。

:假设我们购买了一辆二手车,且从购买到登记期间增加了44英里的里程。下面的代码让我们能够传递这个增量,并相应的增大里程表读数。

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} {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
my_new_car=Car('mayi','a2',2022)
print(my_new_car.get_descriptive_name())

my_new_car.update_odometer(66)
my_new_car.read_odometer()

my_new_car.increment_odometer(44)
my_new_car.read_odometer()

f6137030924e4b688b66439927462345.png

8.3继承

编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本,可使用继承,一个类继承另一个类时,将自动获得另一个类所有属性方法

原有的类称为父类,而新的类称为子类子类继承了父类的所有属性方法同时还可以定义自己的属性和方法

8.3.1子类的方法__init__()

在既有类的基础上编写新类时,通常要调用父类的方法__init__()。这将初始化在父类__init__()方法中定义的所有属性,从而让子类包含这些属性。

让一个类继承另一个类后,就可以添加区分子类和父类所需的新属性和新方法了。

例:下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此可在前面创建Car类的基础上创建新类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=f"{self.year} {self.make} {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
    def fill_gas_tank(self):
        '''父类未被改写'''
        print("yes car!")

class ElectricCar(Car):
    '''电动汽车的独特之处'''
    def __init__(self,make,model,year):
        '''初始化父类的属性,super()函数让子类能调用父类的方法'''
        super().__init__(make,model,year)
        self.battery_size=75
    def describe_battery(self):
        print(f"This car has a {self.battery_size}-KWh battery")
my_tesla=ElectricCar('tesla','model s',2020)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()

93bbe49968a942a28e982e6c38547a15.png

代码解析:
1.创建子类代码时,父类必须包含在当前文件中,且位于子类前面。

2.定义子类时,必须在圆括号内指定父类的名称。方法__init__()接受创建Car实例所需要的信息。

3.super()是一个特殊函数,让我们能够调用父类的方法。父类也成为超类(superclass),名称super由此而来。

4.我们添加了新属性self.battery_size,并设计其初始值(75).根据ElectricCar类创建的所有实例都将包含该属性,但所有Car实例不包含它

8.3.2重写父类方法

对于父类的方法,只要他不符合子类模拟的实物的行为,都可以进行重写。

为此,可在子类中定义一个与要重写的父类方法同名的方法。这样,python将不会考虑这个父类方法,而只关注我们在子类中定义的相应方法。

例:假设Car类有一个名为fill_gas_tamk()的方法,它对全电动汽车来说毫无意义,因此我们需要重写它。
 

class Car:
    --snip--
'''重写父类的方法'''
class ElectricCar(Car):
    '''电动汽车的独特之处'''
    def __init__(self,make,model,year):
        '''初始化父类的属性,super()函数让子类能调用父类的方法'''
        super().__init__(make,model,year)
        self.battery_size=75
    def describe_battery(self):
        print(f"This car has a {self.battery_size}-KWh battery")
    def fill_gas_tank(self):
        '''子类被改写'''
        print("yes Electric!")

9e1c3e455d35449da38db8959a9cb1ed.png

 8.3.3将实例用作属性

使用代码模拟实物时,我们可能会发现自己给类添加的细节越来越多:属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分提取出来,作为一个独立的类。可以将大型类拆分成多个协同工作的小类。

8.4导入类

随着不断给类添加功能,文件可能变得很长,为了让文件尽可能简洁,python允许将类存储在模块中,然后在主程序中导入所需的模块。

 可以参照上一章函数中导入模块和函数

8.5Python标准库

8.5.1定义

python标准库是一组模块,我们安装的python都包含他。

可以使用标准库中的任何函数和类,只需在程序开头包含一条简单的import语句即可。下面我们来看看模块random:

在模块random中,有一个有趣的函数是randint()。它将两个整数作为参数,并随即返回一个位于这两个整数之间(含)的整数。


8.5.2类编码风格

我们有必要熟悉一些与类相关的编码风格问题,在编写的程序较复杂时尤其如此

1.类名应采用驼峰命名法,即将类名中的每个单词首字母都大写,而不使用下划线。

2.实例名和模块名都采用小写格式,并在单词之间加上下划线。

3.对于每个类,都应紧跟在类定义后面包含一个文档字符串。(这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。)

4.每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。

5.可使用空行来组织代码,但不要滥用。

6.在类中,可使用一个空行来分割方法。

7.而在模块中,可使用两个空行来分隔类。

8.需要同时 导入 标准库中的模块和我们编写的模块时,先编写导入标准库模块的import语句,再添加一个空行,然后编写导入我们自己写的模块的import语句。
 

 请指正

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值