Python学习(九)类

Python学习(九)类,第1张

文章目录
        • 1.1 创建和使用类
          • 1.1.1 创建Dog类
            • 1.方法\_init\_()
          • 1.2 根据类创建实例
            • 1.访问属性
            • 2.调用方法
        • 2.使用类和实例
          • 2.1 Car类
          • 2.2 给属性指定默认值
          • 2.3 修改属性的值
            • 1.直接修改属性的值
            • 2.通过方法修改属性的值
          • 3. 通过方法对属性的值进行递增

​ 面向对象编程是最有效的软件编写方法之一。在面向对象编程中,编写表示现实世界中的事物和情景的类。并基于这些类来创建对象。编写类时,定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。使用面向对象编程可模拟现实情景。

​ 根据类来创建对象被称为实例化。这让你能使用类的实例。你将指定可在实例中存储什么信息,定义可对这些实例执行哪些 *** 作。你还将编写一些类来扩展既有类的功能,让相似的类能够高效的共享代码。你将自己编写的类存储在模块中,并在自己的程序文件中导入其他程序员编写的类。

​ 理解面向对象编程有助于你像程序员那样看世界,还可以帮助你真正明白自己编写的代码。不仅是各行代码的作用,还有代码背后更宏大的概念。了解类背后的概念可培养逻辑思维,让你能够通过编写程序来解决遇到的几乎任何问题。

1.1 创建和使用类

​ 使用类几乎可以模拟任何东西。下面编写一个表示小狗的简单Dog类。它表示的不是特定的小狗,而是任何的小狗。对于大多数宠物狗,我们都知道什么呢?宠物狗的名字和年龄。同时我们还知道,大多数的小狗都会蹲下和打滚。我们的Dog类将包含它们。

1.1.1 创建Dog类

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

class Dog():"""一次模拟小狗的简单尝试"""def __init__(self, name, age):
        """初始化属性name和age"""
④        self.age = age
        self.name = name
        
⑤    def sit(self):
        """模拟小狗被命令时蹲下"""
        print self.name.title() + " is sitting."
        
    def roll(self):
        """模拟小狗被命令时打滚"""
        print self.name.title() + " rolled over!"

​ 这里需要注意的地方很多,但不必担心。在本章中充斥着这样的结构,你有大把的机会熟悉它。在①处,定义了一个名为Dog的类。根据约定,在Python中,首字母大写的名称指的是类。这个类定义中的括号是空的,因为我们要从空白创建这个类。在②处,我们编写了一个文档字符串,对这个类的功能作了描述。

1.方法_init_()

​ 类中的函数被称为方法。在前面学到的有关函数的一切都适用于方法,就目前而言,唯一重要的差别是调用方法的方式。③处_init_()是一个特殊的方法,每当根据Dog类创建新实例时,Python都会自动运行它。在这个方法的名称中。开头和结尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。

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

​ ④处定义的两个变量都有前缀self。以self为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。self.age = age在作用与此类似。像这样可通过实例访问的变量称为属性。

​ ⑤处Dog类还定义了另外两个方法:sit()和roll()。由于这两个方法不需要额外的信息,如名字或年龄,因此它们只有一个形参self。

1.2 根据类创建实例

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

​ 下面创建一个表示特定小狗的实例:

class Dog():
    """一次模拟小狗的简单尝试"""

    def __init__(self, name, age):
        """初始化属性name和age"""
        self.age = age
        self.name = name

    def sit(self):
        """模拟小狗被命令时蹲下"""
        print self.name.title() + " is sitting."

    def roll(self):
        """模拟小狗被命令时打滚"""
        print self.name.title() + " rolled over!"


① my_dog = Dog('kitty', 3)print 'My dog name is ' + my_dog.name.title() + ' .'print 'My dog age is ' + str(my_dog.age) + 'years old.'

​ 这里使用前面编写的Dog类。在①处,我们让Python创建一条名字为"kitty",年龄为3的小狗。遇到这行代码的时候,Python使用实参"kitty"和3调用Dog()类中的方法_init_()。方法_init_()创建一个表示特定小狗的实例,并使用我们提供的值来设置属性name和age。方法_init_()并未显示的包含return语句,但Python自动返回一个表示这条小狗的实例。我们将这个实例存储在变量my_dog中。在这里,命名约定很重要。我们通常可以认为首字母大写的名称(如Dog)指的是类,而小写的名称(如my_dog)指的是根据类创建的实例。

1.访问属性

​ 要访问实例的属性,可使用句点表示法。在②处,我们编写了如下的代码来访问my_dog的属性name的值。

my_dog.name

​ 句点表示法在Python中很常用,这种方法演示了Python如何获悉属性的值。在这里,Python先找到实例my_dog,再查找与这个实例相关联的属性name。在Dog类中引用这个属性时,使用self.name。

​ 看一下上述代码的输出:

My dog name is Kitty .
My dog age is 3years old.
2.调用方法

​ 根据Dog类创建实例后,就可以使用句点表示法来调用Dog类中定义的任何方法。下面让小狗蹲下和打滚。

my_dog.sit()
my_dog.roll()

​ 要调用方法,可指定实例的名称(这里是my_dog)和要调用的方法,并用句点分隔它们。遇到代码my_dog.sit()时,Python在类Dog中查找方法sit()并运行其代码。Python会以同样的方式解读代码my_dog.roll()。

​ 可以看到它按照我们的命令做了:

Kitty is sitting.
Kitty rolled over!

这种语法很有用。如果给属性和方法指定了合适的描述性名称,如name,age,sit()和roll(),即便是从未见过代码,我们也能轻松的推断出他是干什么的。

2.使用类和实例

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

2.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


③ my_new_car = Car("audi", "a4", 2020)
print my_new_car.get_descriptive_name()

​ 在①处,我们定义了方法_init_()。与前面的Dog类中的一样,这个方法的第一个形参self。我们还在这个方法中包含了另外三个形参,make,model和year。方法_init_()接受这些形参的值,并将它们存储在根据这个类创建的实例和属性中。创建新的Car时,我们需要指定气制造商,型号和生产年份。

​ 在②处,我们定义了一个名为get_descriptive_name()的方法,它使用属性year,make,model创建一个对汽车进行描述的字符串,让我们无需分别打印每个属性的值。为在这个方法中访问属性的值,我们使用了self.name,self.model,self.year。在③处,我们根据Car类创建了一个实例,并将其存储到变量my_new_car中。接下来调用方法get_descriptive_name(),指出我拥有的是一辆什么样的汽车。

2020 audi a4

​ 为了让这个类更有趣,下面给它添加一个随时间变化的属性,它存储汽车的总里程。

2.2 给属性指定默认值

​ 类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。在有些情况下,如设置默认值时,在方法_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 = str(self.year) + " " + self.make + " " + self.model
        return long_name

②    def read_odometer(self):
        """打印一条指出汽车里程的消息"""
        print "This car has " + str(self.odometer_reading) + " miles on it."

my_new_car = Car("audi", "a4", 2020)
print my_new_car.get_descriptive_name()
my_new_car.read_odometer()

​ 现在,当Python调用方法_init_()来创建新实例时,将像前一个示例以属性的方式存储制造商等。接下来,Python将创建一个名为odometer_reading的属性,①处将其初始值设置为0。在②处,我们还定义一个名为read_odometer的方法,它让你能够轻松的获取汽车的里程数。

​ 在一开始的时候,汽车的里程数为0。

2020 audi a4
This car has 0 miles on it.

​ 但是在真正出售汽车时,为0里程的并不多,因此我们需要一个修改该属性的值的途径。

2.3 修改属性的值

​ 可以以三种不同的方式修改属性的值,①直接通过实例进行修改,②通过方法进行设置,③通过方法进行递增(增加特定的值)。下面依次介绍这些方法。

1.直接修改属性的值

​ 要修改属性的值,最简单的方式是通过实例直接访问它。下面的代码直接将里程数读书设置为100.

① my_new_car.odometer_reading = 100
my_new_car.read_odometer()

​ 在①处,我们使用句点表示法来直接访问并设置汽车的属性odometer_reading。这行代码让Python在实例my_new_car中找到属性odometer_reading,并将该属性的值设置为100。

2020 audi a4
This car has 100 miles on it.

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

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 = str(self.year) + " " + self.make + " " + self.model
        return long_name

    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", 2020)
print my_new_car.get_descriptive_name()
# my_new_car.odometer_reading = 100
② my_new_car.update_odometer(100)
my_new_car.read_odometer()

​ 对Car类所做的唯一修改是在①处添加了方法update_odometer()。这个方法接收一个里程值,并将其存储到self.odometer_reading中。在②处,我们调用了update_odometer(),并向它传递了实参100(该实参对应方法定义中的形参mileage)。它将里程表的读数设置为100。

2020 audi a4
This car has 100 miles on it.

​ 接着对方法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 = str(self.year) + " " + self.make + " " + self.model
        return long_name

    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!"

my_new_car = Car("audi", "a4", 2020)
print my_new_car.get_descriptive_name()
# my_new_car.odometer_reading = 100
my_new_car.update_odometer(100)
my_new_car.update_odometer(0)
my_new_car.read_odometer()

​ 现在,update_odometer()在修改属性前先检查指定的读数是否合理。如果新指定的里程大于或等于原来的里程,将里程改为新指定的里程。否则我们就发出警告,指出不可以将里程往回拨。

2020 audi a4
You can't roll back an odometer!
This car has 100 miles on it.
3. 通过方法对属性的值进行递增

​ 有时候需要将属性值递增特定的量,而不是将其设置为全新的值。假设我们购买了一辆二手车,且从购买到登记期间增加了100公里,下面的方法让我们能够传递这个增量,并相应的增加里程表读数。

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

    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

② my_old_car = Car("audi", "a4", 2020)
print my_old_car.get_descriptive_name()
③ my_old_car.update_odometer(100)
my_old_car.read_odometer()
④ my_old_car.increment_odometer(100)
my_old_car.read_odometer()

​ 在①处,新增的方法increment_odometer()接收一个单位为里的数字,并将其加入到self.odometer_reading中。在②处,我们创建了一辆二手车,my_old_car。在③处,我们调用方法update_odometer()并传入100,将这辆二手车的里程表的读数设置为100。在④处,我们调用increment_odometer()并传入100,以增加从购买到登记期间的100里。

2020 audi a4
This car has 100 miles on it.
This car has 200 miles on it.

​ 你可以轻松的修改这个方法,以禁止增量为负数,从而防止有人利用它来回拨里程表。


今天先写到这喽!下一篇开始从类的集成开始。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/801933.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-07
下一篇 2022-05-07

发表评论

登录后才能评论

评论列表(0条)

保存