1.创建和使用类

1.1创建dog类

class Dog:
    """模拟小狗"""
    
    def __init__(self, name, age):
        """初始化属性"""
        self.name = name
        self.age = age
        
    def sit(self):
        """模拟小狗坐下"""
        print(f"{self.name} is sitting now")
        
    def roll_over(self):
        """模拟小狗打滚"""
        print(f"{self.name} rolled over")
  • 类中的函数称为方法
  • 方法_init_()(左右各双下划线)定义时,形参self是必不可少的,而且必须位于其他形参前面
  • 为什么self在方法定义时必不可少呢?因为python调用这个方法创建实例的时候,将自动传入实参self,每个与实例相关联的方法调用都自动传递实参self,是一个指向实例本身的引用
  • self.name = name中的以self开头的name可以供类中的所有方法使用,可以通过类的任何实例来访问,self.name = name获取与形参name相关联的值,并赋给变量name,像这样可通过实例访问的变量称为属性
  • 在Dog类中还定义了另外两个方法,因为这两个方法中不需要额外的信息,因此只有一个形参self。之后会在创建的实例中能够访问这些方法

1.2 根据类创建实例

class Dog:
    """模拟小狗"""
    
    def __init__(self, name, age):
        """初始化属性"""
        self.name = name
        self.age = age
        
    def sit(self):
        """模拟小狗坐下"""
        print(f"{self.name} is sitting now")
        
    def roll_over(self):
        """模拟小狗打滚"""
        print(f"{self.name} rolled over")
        
my_dog = Dog('willie', '6')   

1.2.1访问属性

my_dog.name
  • 访问实例的属性,使用句点表示法

1.2.2调用方法

  • 根据类创建实例后,能够使用句点表示法来调用方法

    例如:

    my_dog = Dog('willie', '6')
    my_dog.sit()
    my_dog.roll_over()
    

1.2.3创建多个实例

  • 可按需求根据类创建多个实例

2.使用类和实例

2.1给属性指定默认值

示例:

class Restaurant:
    """创建一个餐馆的实例"""

    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type
        self.served_number = 0

    def describe_restaurant(self):
        print(f"restaurant's name is {self.restaurant_name}"
              f"\ncuisine type is {self.cuisine_type}")

    def open_restaurant(self):
        print("this restaurant is opening")

    def set_number_served(self, customer_number):
        self.served_number = customer_number

    def increment_number_served(self, number):
        self.served_number += number
        
        
restaurant = Restaurant('beijingkaoya', 'beijingcai')
restaurant.describe_restaurant()
restaurant.open_restaurant()
  • 有时属性无须通过形参来定义,可在方法_init_()中为其指定默认值
  • 在示例中,设置类Restaurant中的served_number变量默认值为0,使用self.served_number = 0

2.2修改属性的值

2.2.1直接修改属性的值

  • 最简单的方式就是访问属性并修改它
  • 修改示例中的served_number默认值的方式为restaurant.served_number = 10

2.2.2通过方法修改属性值

  • 在类中添加一个方法用来修改属性值

    class Restaurant:
        """创建一个餐馆的实例"""
    
        def __init__(self, restaurant_name, cuisine_type):
            self.restaurant_name = restaurant_name
            self.cuisine_type = cuisine_type
            self.served_number = 0
    
        def describe_restaurant(self):
            print(f"restaurant's name is {self.restaurant_name}"
                  f"\ncuisine type is {self.cuisine_type}")
    
        def open_restaurant(self):
            print("this restaurant is opening")
    
        def set_number_served(self, customer_number):
            self.served_number = customer_number
    
        def increment_number_served(self, number):
            self.served_number += number
    
        def update_served_number(self, sernum):
            self.served_number = sernum
    
    
    restaurant = Restaurant('beijingkaoya', 'beijingcai')
    restaurant.describe_restaurant()
    restaurant.open_restaurant()
    restaurant.update_served_number(30)
    print(restaurant.served_number)
    
  • 在示例的Restaurant类中添加了一个update_served_number的方法,使用该方法修改served_number的值,但是需要传递实参给update_served_number方法

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

  • 有时需要把属性中的值设置为递增特定的量,而不是设置为新的值。如示例中,served_number表示可以服务的客人数量,可能这个数量是可以递增的。

    class Restaurant:
        """创建一个餐馆的实例"""
    
        def __init__(self, restaurant_name, cuisine_type):
            self.restaurant_name = restaurant_name
            self.cuisine_type = cuisine_type
            self.served_number = 0
    
        def describe_restaurant(self):
            print(f"restaurant's name is {self.restaurant_name}"
                  f"\ncuisine type is {self.cuisine_type}")
    
        def open_restaurant(self):
            print("this restaurant is opening")
    
        def set_number_served(self, customer_number):
            self.served_number = customer_number
    
        def increment_number_served(self, number):
            self.served_number += number
    
        def update_served_number(self, sernum):
            self.served_number = sernum
    
    
    restaurant = Restaurant('beijingkaoya', 'beijingcai')
    restaurant.describe_restaurant()
    restaurant.open_restaurant()
    restaurant.increment_number_served(10)
    restaurant.update_served_number(30)
    print(restaurant.served_number)
    
  • 在示例中定义了一个方法increment_number_served()用来给served_number设置递增的量,在创建实例的时候需要给increment_number_served()传递一个固定的递增的值

  • 增量可以是正值也可以是负值,根据具体情况而定

3.继承

3.1子类的方法__init__()

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

    class Restaurant:
        """创建一个餐馆的实例"""
    
        def __init__(self, restaurant_name, cuisine_type):
            self.restaurant_name = restaurant_name
            self.cuisine_type = cuisine_type
            self.served_number = 0
    
        def describe_restaurant(self):
            print(f"restaurant's name is {self.restaurant_name}"
                  f"\ncuisine type is {self.cuisine_type}")
    
        def open_restaurant(self):
            print("this restaurant is opening")
    
        def set_number_served(self, customer_number):
            self.served_number = customer_number
    
        def increment_number_served(self, number):
            self.served_number += number
    
    
    class Fav:
        def __init__(self, favor):
            self.favor = favor
    
        def display_taste(self):
            print(f"favorite taste is :{self.favor}")
    
    
    class IceCreamStand(Restaurant):
        def __init__(self, restaurant_name, cuisine_type):
            """初始化父类的属性"""
            super().__init__(restaurant_name, cuisine_type)
            """调用父类的方法"""
            self.favors = Fav('巧克力')
    
    
    ice = IceCreamStand('DQ', 'icecream')
    ice.open_restaurant()
    ice.describe_restaurant()
    ice.favors.display_taste()
    
  • 创建子类的时候,父类必须包含在当前文件中并且在子类前面
  • super()是一个特殊的函数,能够调用父类的方法

3.2给子类定义属性和方法

class IceCreamStand(Restaurant):
    def __init__(self, restaurant_name, cuisine_type):
        """初始化父类的属性"""
        super().__init__(restaurant_name, cuisine_type)
        """调用父类的方法"""
        self.favors = Fav('巧克力')

3.3重写父类的方法

  • 对于父类的方法,只要不符合子类模拟的实物行为,都可以进行重写
  • 可以在子类中定义一个与要重写的父类方法同名的方法,调用子类中重写的方法时,Python忽略父类中同名的方法

3.4将实例用作属性

class Fav:
    def __init__(self, favor):
        self.favor = favor

    def display_taste(self):
        print(f"favorite taste is :{self.favor}")


class IceCreamStand(Restaurant):
    def __init__(self, restaurant_name, cuisine_type):
        """初始化父类的属性"""
        super().__init__(restaurant_name, cuisine_type)
        """调用父类的方法"""
        self.favors = Fav('巧克力')
  • 在子类IceCreamStand中新增了一个favors属性,这个属性关联的是一个Fav实例

4.导入类

导入类的语句与导入函数的语句类似

4.1导入单个类

  • from 模块名 import 类名

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

  • 虽然一个文件中的类应该有某种相关性,但是可以根据需要将不同的类放在同一模块文件中

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

  • from 模块名 import 类名1,类名2,类名3

4.4导入整个模块

  • 可以导入整个模块,再使用句点表示法访问需要的类

  • import 模块名
    m = 模块名.类名
    

4.5导入模块中的所有类

  • from 模块名 import *
  • 不推荐这种方式导入,因为如果导入了和主程序同名的类,将引发难以诊断的错误
  • 需要从一个模块中导入很多类时,最好导入整个模块,再使用句点表示法来访问类

4.6在一个模块中导入另一个模块

4.7使用别名

  • from 模块名 import 类名 as 别名

注意:一开始应让代码结构尽可能简单。先尽可能在一个文件中完成所有项目的工作,确定一切能够正常运行后,再讲类移动到独立的模块中

练习:

from time import sleep


class Clock(object):#Python3默认加载object,即便没有加上object
    """定义一个时钟的类"""

    def __init__(self, hour=0, minute=0, second=0):
        self.hour = hour
        self.minute = minute
        self.second = second

    def run(self):
        """走表"""
        self.second += 1
        if self.second == 60:
            self.second = 0
            self.minute += 1
        if self.minute == 60:
            self.hour += 1
            self.minute = 0
        if self.hour == 24:
            self.hour = 0

    def show(self):
        """显示时间"""
        return '%02d:%02d:%02d' % \
               (self.hour, self.minute, self.second)


def main():
    c = Clock(23, 59, 50)
    while True:
        print(c.show())
        sleep(1)
        c.run()


if __name__ == '__main__':
#只有main()函数在当前模块中才可以执行,被调用后,main()下面的代码就不会被执行
    main()
posted @ 2021-12-02 18:08  写代码的小灰  阅读(73)  评论(0)    收藏  举报