Python:类 《Python编程:从入门到实践 第2版》笔记

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

class Person:
    '''一个person类'''
    def __init__(self, name=' ', age=1, sex=' ', address='', phonenum=''):
        """初始化属性name和age"""
        self.name = name
        self.age = age
        self.sex = sex
        self.address = address
        self.phonenum = phonenum
        self.Info = {'name': name,
                   'age': age,
                   'sex': sex,
                   'address': address,
                   'phonenum': phonenum,
                   }

    def setname(self, name):
        self.name = name

    def getname(self):
        return self.name

    def setage(self, age):
        self.age = age

    def getage(self):
        return self.age

在这里我们创建了一个Person类,这个类中有init、setname,getname,setage,getage等方法。

方法__init__()

类中的函数称为方法。 你在前面学到的有关函数的一切都适用于方法,就目前而言, 唯一重要的差别是调用方法的方式。init()方法是一个特殊的方法,每当我们创建Person类的一个实例的时候,Python都会自动运行它。

在这个方法的名称中, 开头和末尾各有两个下划线,这是一种约定, 旨在避免Python默认方法与普通方法发生名称冲突。 务必确保__init__()的两边都有两个下划线, 否则当你使用类来创建实例时, 将不会自动调用这个方法, 进而引发难以发现的错误。

在这里__init__()方法定义成包含三个形参:self、name和age,在这个方法的定义中,形参self必不可少,而且必须位于其他形参的前面。

为何必须在方法定义中包含形参self呢? 因为Python调用这个方法来创建Person实例时, 将自动传入实参self。 每个与实例相关联的方法调用都自动传递实参self, 它是一个指向实例本身的引用, 让实例能够访问类中的属性和方法。 创建Person实例时, Python将调用Person类的方法__init__()。 我们将通过实参向Person()传递名字和年龄, self会自动传递, 因此不需要传递它。 每当根据Dog类创建实例时, 都只需给最后两个形参(name和age) 提供值。

以self为前缀的变量可供类中的所有方法使用, 可以通过类的任何实例来访问。

根据类创建实例

person1 = Person('Wu', 23, 'male', 'Jiangsu,Nanjing', '1234567890')
print(f"I'm {person1.name}")
print(person1.Info)
name = person1.getname()
print(f"My name is {name}")

我们通过Person类来实例化变量person1,通过person1 = Person('Wu', 23, 'male', 'Jiangsu,Nanjing', '1234567890') 这一语句,即实例化了一个Person类的对象person1,person1具有name,age,sex等属性。

访问属性

要访问实例的属性, 可使用句点表示法。例如print(f"I'm {person1.name}") ,这里使用person1.name,就可以访问person1的name属性,句点表示法在Python中很有用,在这里,Python先找到实例person1,再获取与实例相关的属性name。

调用方法

在调用方法上,同样可以使用句点表示法。例如name = person1.getname() 通过调用getname()方法来获取person1的name属性。

使用类和实例

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

Car类

class Car:
"""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):
        return (str)(self.make + self.model + self.year)

    def read_odometer(self):
        print(f"This car has {self.odometer_reading} miles on it")

在构造函数中,有一个自有变量odometer_reading初始化为0,该变量并不需要从外界传入参数,可以理解一辆新车的里程数应该为0。

if __name__ == '__main__':

    car1 = Car('Hongqi', 'L5', '2009')
    print(car1.get_descriptive_name())
    car1.read_odometer()

Hongqi L5 2009
This car has 0 miles on it

可以看到这里我通过Car类实例化一个对象car1,并给出一些属性值,然后我们使用句点表示法,使用了一些Car类的函数,输出car1的信息。

修改属性的值

我们能以三种方式修改属性的值: 直接通过实例进行修改, 通过方法进行设置, 以及通过方法进行递增(增加特定的值) 。

直接修改属性的值

car1.odometer_reading = 500
car1.read_odometer()

This car has 500 miles on it

假设这辆车已经开了500英里,那我们可以通过句点表示法直接访问car1实例的属性odometer_reading来修改为500,

通过方法修改属性的值

def update_odometer(self, mileage):
    self.odometer_reading = mileage

我们在Car类中定义一个新的函数update_odometer()方法,该方法有一个self参数和一个mileage,在这个方法中可以对odometer_reading重新设置值。

car1.update_odometer(500)
car1.read_odometer()

This car has 500 miles on it

通过调用car1的update_odometer()方法,我们可以对其里程数进行设置达到与通过访问属性进行设置一样的目的。

注释:Python的封装,在我看来是一种不够彻底的封装,如果能够在类的外部来对某个实例化的对象的属性进行直接访问,我认为是十分不安全的,因为稍微熟悉代码的人就可以对其做出修改。

继承

面向对象的编程的特点之一就是继承。编写类时,并非总要从空白开始,如果要编写的类是另一个现成类的特殊版本,可以进行继承。被继承的类成为父类,新继承而来的类成为子类。即继承使类之间具有了父子关系,当父类做某种改动的时候,就可能会对子类造成某些影响,而子类做一些改动的时候,并不会对父类有什么影响。

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

子类的__init__()方法

子类会继承父类的__init__()方法,并且通常调用调用父类的初始化方法,这并不是说一定要进行调用,

class ElectricCar(Car):
"""Electric Car类"""

    def __init__(self, make, model, year, battery):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
        self.battery = battery

我们写一个电动汽车类,在这里我们写了一个初始化函数,这个函数的参数与父类Car类非常相似,只是多了一个battery这个参数用来记录车辆现在的电量。

ecar1 = ElectricCar('Wuling', 'MiniEV', '2022', 300)
ecar1.read_odometer()

This MiniEV has 0 miles on it

虽然我没有在ElectricCar中定义函数read_odometer()函数,但是由于EletricCar是继承于Car类,所以有Car的所有方法。当然在ElectricCar类的__init__()函数在很多方面与父类Car的__init__()函数相似,所以我们也可以调用super()函数,让ElecteicCar实例包含这个方法中定义的所有属性。父类也称为超类(Superclas

s),名称super由此而来。

class ElectricCar(Car):
"""Electric Car类"""

    def __init__(self, make, model, year, battery):
        super().__init__(make, model, year)
        self.battery = battery

在这里我调用父类Car的__init__()函数来初始化一部分数据。

注释:继承最大的好处是代码的复用性提高,很多代码完全没必要重复。而对于一些具有共同特征的类,我们可以抽象出来一个更底层的类作为父类,让其他类在这个父类上扩展。例如ElectricCar、Truck、Bus等有一些共同的特征像是制造商、型号、出产年份等信息,这些共有信息就可以抽象出一个底层的Car类。这样当我们为Electric、Truck、Bus等类添加某些共有的属性或方法时,就可以直接在Car类上进行更改,而不必对每个类都进行修改。其次,每个类所具有的方法或属性更加符合自己的需要,保持自己的个性。总之,继承确实能够帮助提高代码的复用性,并且使得程序逻辑更好。

给子类定义属性和方法

显然,ElectricCar类可以做一些改进,初始化函数的battery到底是指该车的现有电量还是指最大电量呢,我们应该将这个在程序中体现出来,

class ElectricCar(Car):
    """Electric Car类"""

    def __init__(self, make, model, year, max_battery, cur_battery=0):
        super().__init__(make, model, year)
        self.__MAXBATTERY = max_battery#我们将maxbattery设置为私有变量,让其不能在类外随意更改
        self.cur_battery = cur_battery

    def get_MaxBattery(self):
        return self.__MAXBATTERY

    def reset_MaxBattery(self, max_battery):
        """
        更改私有变量必须要通过类的方法来进行更改。
        """
        self.__MAXBATTERY = max_battery

    def get_CurBattery(self):
        return self.cur_battery

    def set_CurBattery(self, cur_battery):
        self.cur_battery = cur_battery

这里,我们将最大电量值设为一个私有属性,私有属性是指不能在类地外部被使用或直接访问。

注释:__private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。

我们要尽可能确保数据的安全,所以总共有两个电量值,一个是最大电量,这个值一旦被设定就不应该轻易更改,另一个则是目前电量,它是实时变化的。ElectricCar类继承于Car类,但是它又拥有属于自己的属性MAXBATTERY和cur_battery。并且拥有自己的方法get_MaxBattery()等。

ecar1 = ElectricCar('Wuling', 'MiniEV', '2022', 300, 0)
ecar1.read_odometer()
# print(ecar1.__MAXBATTERY)
print(ecar1.get_MaxBattery())
ecar1.reset_MaxBattery(250)
print(ecar1.get_MaxBattery())
ecar1.set_CurBattery(120)
print(ecar1.get_CurBattery())

This MiniEV has 0 miles on it
300
250
120

重写父类方法

我们并不是一定要完全按照父类的方法来执行,有时候父类的某些方法对于子类来说并不合适,那我们就可以重写父类的方法。其原理就是重载函数。首先重写父类的方法,一定是方法名与父类中的方法名完全相同,这样才是重写。

当Python执行该类的实例,并调用该方法的时候,并不会执行父类的方法,因为子类中的同名方法已经将父类的方法覆盖掉。其实也是相当好理解,就是程序不会舍近求远,程序会优先执行与其关系最密切的类的方法。既然子类中有该方法,就不会去执行父类的方法,如果子类中没有该方法,就会向下寻找其父类的该方法。

将实例用作属性

属性并不是要求其是一个基本的数据类型,我们可以把一个类的实例作为属性,对于电动汽车来说,当我们逐渐丰富代码时,可以考虑把电池也作为一个类。

class Battery:
    """ Battery类"""
    def __init__(self, max_battery, cur_battery=0):
        self.__MAXBATTERY = max_battery
        self.cur_battery = cur_battery

    def get_MaxBattery(self):
        return self.__MAXBATTERY

    def reset_MaxBattery(self, max_battery):
    """
    更改私有变量必须要通过类的方法来进行更改。
    """
        self.__MAXBATTERY = max_battery

    def get_CurBattery(self):
        return self.cur_battery

    def set_CurBattery(self, cur_battery):
        self.cur_battery = cur_battery

这是一个电池类,我们在原来的ElectricCar中抽象出来的。

class ElectricCar(Car):
    """Electric Car类"""

    def __init__(self, make, model, year, max_battery, cur_battery=0):
        super().__init__(make, model, year)
        self.battery = Battery(max_battery, cur_battery)

    def get_MaxBattery(self):
        return self.battery.get_MaxBattery()

    def reset_MaxBattery(self, max_battery):
        self.battery.reset_MaxBattery(max_battery)

    def get_CurBattery(self):
        return self.battery.get_CurBattery()

    def set_CurBattery(self, cur_battery=0):
        self.battery.set_CurBattery(cur_battery)

可以看到,在ElectricCar类的__init__()方法中我们创建了一个属性battery,它是Battery类的实例self.battery = Battery(max_battery, cur_battery) ,这是一个很好的方法。

Python标准库

Python标准库是一组模块, 我们安装的Python都包含它。我们可以通过import关键字来导入这些模块。

from random import randint

if __name__ == '__main__':
    number = randint(0, 1000)
    standardTimes = 10
    playerAnswer = -1
    playerTimes = 0
    while(playerAnswer != number and playerTimes < 15):
        playerAnswer = int(input("input your guess: "))
        playerTimes += 1
        if playerAnswer > number:
            print("too big")
        elif playerAnswer < number:
            print("too small")
        else:
            break

    if playerTimes <= 10:
        print("score:100, Good! ")

    elif playerTimes <= 15:
        print("score:75")

    else:
        print("score:60")

input your guess: 500
too small
input your guess: 750
too small
input your guess: 875
too small
input your guess: 937
too big
input your guess: 906
too small
input your guess: 921
too small
input your guess: 929
too big
input your guess: 925
too big
input your guess: 923
score:100, Good! 

该程序是一个猜数字的游戏,由程序随机选出一个在01000之间的数字,然后由玩家来进行猜测。程序会提示玩家该次猜测是大于正确答案还是小于正确答案,并且玩家最多有15次猜测机会。通常来说,猜测一个在01000之间的数字,最多只需要10次机会,所以能在10次以内猜中正确答案的,会得到高的分数。

类编码风格

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

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

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

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

s

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《Python编程:从入门实践》第2是一本非常好的Python编程入门书籍,适合初学者学习Python编程语言。本书从基础语法入手,逐步介绍Python的各种特性和应用,包括函数、模块、面向对象编程、文件操作、异常处理、GUI编程等。此外,本书还提供了大量的实例和练习,帮助读者巩固所学知识,提高编程能力。总之,这是一本非常实用的Python编程入门书籍,值得推荐给初学者。 ### 回答2: 《Python编程入门实践》第2是一本适合初学者学习Python入门书籍。本书从Python的基本语法、变量、数据型和循环结构等基础知识开始,逐步介绍了Python的高级概念和实践技巧。 本书的第一部分主要介绍了Python编程的基础知识。其中包括Python语言的基本语法、变量、数据型和流程控制等内容。本书在讲解这些内容的时候,会结合具体的案例来讲解,以帮助读者更好地掌握Python编程的基础知识。 本书的第二部分主要介绍了Python的高级概念和实践技巧。其中包括函数、、模块、异常处理等内容。这些内容是Python编程的关键性概念,对于想要深入学习Python编程的读者来说,是非常必要的。 本书的第三部分主要是以实际项目作为实践,帮助读者了解如何使用Python编写实际项目。其中包括Web应用程序、数据可视化、游戏开发等内容。这些案例不仅可以帮助读者掌握Python编程技能,还可以帮助读者了解如何把Python应用到实际项目中。 总之,如果你是一位初学者或想深入学习Python编程的读者,那么《Python编程入门实践》第2是一本非常不错的书籍。它不仅能够帮助你掌握Python编程的基础知识,还可以帮助你了解Python编程中的高级概念和实践技巧。并且通过实践案例,还可以帮助你了解如何将Python应用到实际项目中,具有很高的实用性。 ### 回答3: 《Python编程入门实践》第2是一本入门Python编程教材,主要适用于初学者。本书共分为两部分,第一部分介绍了Python编程的基础知识、程序设计和常用的数据结构和算法等,第二部分则通过实践项目的方式进一步深入学习Python编程,包括了Web应用、数据可视化、人工智能、游戏编程等方面。 在第一部分,作者通过几个简单易懂的项目引导读者逐步了解Python编程的基础语法和常见作用,例如如何进行数据型转换、字符串格式化、列表操作、函数定义等等。此外,在掌握了Python编程的基础语法后,读者还能学习到一些大型项目开发中常用的工具和技巧,如代码重构、调试技巧和本控制工具等。 在第二部分,作者通过多个实际项目的演示,介绍了如何用Python编写各种实用的应用程序,并深入掌握各种框架和技术,比如Flask/Django Web框架、数据可视化工具和机器学习等等,使读者能够更好的理解Python在实际开发中应用的重要性。 总之,《Python编程入门实践》第2是一本非常好的Python编程入门教材,能够帮助读者从零开始掌握Python编程,而且对于实际应用也有非常详细的介绍。无论是完全的初学者还是有经验的开发者,都能从本书中获得一些有用的技巧和经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SUNX-T

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

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

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

打赏作者

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

抵扣说明:

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

余额充值