8.Python类的创建,继承,导入

知识点

  1. 类的名字要首字母大写。
  2. 类由属性和方法组成。
  3. 类里的函数称为方法。
  4. 可以用一个类创造多个实例,只要实例名不同即可。
  5. 类里面的所有方法都需要self参数。
  6. 子类可以在super().init()语句的括号中添加新的参数,使子类不仅仅是继承父类的所有参数。
  7. 一个模块中可以存储多个类。

1. 创建一个类

class Dog():    
#创建一个Dog类,注意首字母大写和冒号
    """A simple attempt to model a dog."""  #docstring
    
    def __init__(self, name, age):      
        """Initialize name and age attributes."""   #docstring
        self.name = name
        self.age = age
        
    def sit(self):
        """Simulate a dog sitting in response to a command."""
        print(self.name.title() + " is now sitting.")

    def roll_over(self):
        """Simulate rolling over in response to a command."""
        print(self.name.title() + " rolled over!")

注意:

  1. 类名要首字母大写
  2. 类名后面的括号里面为,表示这是从零开始创建的类,没有继承其他类
  3. --init--()方法较为特殊,用类创建实例时,自动调用--init--()方法,其他方法则需要输入代码调用
  4. 类中的方法必须要有一个self参数,且要将self参数放在最前面
  5. --init--()方法下面定义的变量都要有self前缀,这样可以被类中所有的方法调用
  6. 可以通过实例查看的变量称为属性

2. 创建一个实例

格式: 实例名=类名(参数)

输入:

class Dog():    
---snip---      #Dog类具体细节见上,这=这里省略

my_dog = Dog('willie', 6)

print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")   #数字要转为字符
my_dog.sit()

输出:

My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.

(1) 获取属性

格式:instance_name.attribute_name

上例中,生成实例时,括号中的‘Willie’一开始还只是一个字符串,被作为实参传送给类中name形参后,被self.name = name语句转换为类的属性,并使用my_dog.name来获取属性的值。

(2)调用方法

格式:instance_name.method_name

上例中,当Python读到my_dog.sit(),Python为转向Dog类,执行里面的sit()方法。

3. 使用类和实例

输入:

class Car():
    """A simple attempt to represent a car."""

    def __init__(self, manufacturer, model, year):
        """Initialize attributes to describe a car."""
        self.manufacturer = manufacturer
        self.model = model
        self.year = year
        
    def get_descriptive_name(self):
        """Return a neatly formatted descriptive name."""
        long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
        return long_name.title()

my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())

输出:

2016 Audi A4

(1) 给属性设置默认值

在上例的基础上,添加odometer_reading属性和read_odometer方法,并将odometer_reading属性默认值设为0。

输入:

class Car():
    """A simple attempt to represent a car."""

    def __init__(self, manufacturer, model, year):
        """Initialize attributes to describe a car."""
        self.manufacturer = manufacturer
        self.model = model
        self.year = year
        self.odometer_reading = 0   #odometer_reading默认值设为0
        
    def get_descriptive_name(self):
        """Return a neatly formatted descriptive name."""
        long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
        return long_name.title()

    def read_odometer(self):
        """Print a statement showing the car's mileage."""
        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.

(2) 更改默认值

1.直接法:

格式: instance_name.attribute_name = new_value

输入:

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

my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())

my_new_car.odometer_reading = 23    #更改默认值
my_new_car.read_odometer()

输出:

2016 Audi A4
This car has 23 miles on it.

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

输入:

class Car():
---snip---
def update_odometer(self, mileage):
        """
        Set the odometer reading to the given value.
        Reject the change if it attempts to roll the odometer back.
        """
        if mileage >= self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")

my_new_car=Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())

my_new_car.update_odometer(300)
my_new_car.read_odometer()

通过类里的update_odometer方法改变属性的值。需要传参。

输出:

2016 Audi A4
This car has 300 miles on it.

4. 继承

类不一定从零开始创建,一个新类可以从另外一个类中继承所有的属性和方法,并且还可以为自己添加新的类和方法。

格式:class child_class (parent_class)

child_class为子类,parent_class为父类。

(1) 利用继承创建一个新类

输入:

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

class ElectricCar(Car):
    """Models aspects of a car, specific to electric vehicles."""

    def __init__(self, manufacturer, model, year):
        """
        Initialize attributes of the parent class.
        Then initialize attributes specific to an electric car.
        """
        super().__init__(manufacturer, model, year)

my_tesla = ElectricCar('tesla', 'roadster', 2015)
print(my_tesla.get_descriptive_name())

输出:

2015 Tesla Roadster

注意:

  1. __init__方法接收创建一个Car类所需的所有参数,并且初始化Car类。
  2. 初始化Car类后,super()函数建立父类与子类的连接,让ElectricCar类继承Car类中所有的方法和属性,super().init(...)语句的括号中,可以添加子类需要的新参数。

(2) 为子类添加属性和方法

可以直接在super().__init__(...)语句下面添加子类独有的属性。

输入:

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

class ElectricCar(Car):
    """Models aspects of a car, specific to electric vehicles."""

    def __init__(self, manufacturer, model, year):
        """
        Initialize attributes of the parent class.
        Then initialize attributes specific to an electric car.
        """
        super().__init__(manufacturer, model, year)
        self.battery_size = 70  #添加新属性,并且设置默认值
        
     def describe_battery(self):    #添加新方法
        """Print a statement describing the battery size."""
        print("This car has a " + str(self.battery_size) + "-kWh battery.") 

my_tesla = ElectricCar('tesla', 'roadster', 2015)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()

输出:

2015 Tesla Roadster
This car has a 70-kWh battery.

(3) 重写父类方法

子类会继承父类所有的方法和属性,当某个继承来的方法需要更改时,我们只需要用和原来方法相同的方法名,重新定义方法。

例如,电动车没有油箱,所以我们要把ElectricCar类中的fill_gas_tank方法更改一下。

输入:

class ElectricCar(Car)
---snip---

    def fill_gas_tank():
        """electric cars don't have gas tanks"""
        print("This car doesn't need a gas tank!")

这样,新的fill_gas_tank方法会覆盖从Car中继承的fill_gas_tank方法。

(4) 将实例作为属性

当属性和方法较多时,可以将一部分属性和方法分离出来,作为单独的类。

输入:

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

class Battery():
    """A simple attempt to model a battery for an electric car."""

    def __init__(self, battery_size=60):
        """Initialize the batteery's attributes."""
        self.battery_size = battery_size

    def describe_battery(self):
        """Print a statement describing the battery size."""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")  
        
class ElectricCar(Car):
    """Models aspects of a car, specific to electric vehicles."""

    def __init__(self, manufacturer, model, year,battery_size):
        """
        Initialize attributes of the parent class.
        Then initialize attributes specific to an electric car.
        """
        super().__init__(manufacturer, model, year)
        self.battery = Battery(battery_size)

my_tesla = ElectricCar('tesla', 'roadster', 2015,70)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()

输出:

2015 Tesla Roadster
This car has a 70-kWh battery.

上例将与电池相关的属性和方法分离出来,作为一个新类。通过将类Battery的实例作为类ElectricCar的battery属性,将两个类关联起来,虽然类Battery中的参数battery_size默认值为60,却可以由实例my_tesla的实参改为70。

5. 导入类

和函数相同,当程序非常复杂时,我们可以将类单独保存为一个模块,在主程序的开头导入模块即可。

(1)单独导入一个类

导入格式:

from module_name import Class_name

使用格式:

instance_name = Class(arguments)
instance_name.attribute
instance_name.method(arguments)

(2)导入多个类

导入格式:

from module_name import Class1_name,Class2_name,...,Classn_name

使用格式:

instance_name = Class(arguments)
instance_name.attribute
instance_name.method(arguments)

(3)导入整个模块

导入格式:

import module_name

使用格式:

instance_name =module_name.Class(arguments)
instance_name.attribute
instance_name.method(arguments)

只是在用导入的类生成实例时,需要加上module_name,其他时候不需要。

(4)导入模块中所有类(不推荐)

导入格式:

from module_name import *

不推荐这种方法,会弄不清到底使用了哪些类,并且可能造成模块中的类名与主程序的类名冲突。

(5)在一个模块中导入另一个模块

需要用到继承时使用,与主程序导入模块的格式相同

推荐格式:

from module_name import Class_name

6. 类编程风格

  • 类名应该采用驼峰命名法,即不使用下划线,每个单词首字母大写
  • 实例名和模块名需要小写,单词间用下划线隔开
  • 每个类定义的下面都应该紧跟一个docstring,类的每个方法下面也应该有docsting来描述其功能
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 在开始阅读前,说我知识浅薄无知也好,实际上我的确是抱着观看一本在文学界的种田文而来的。可看完今天的分量,蓦然发现哦...
    四眼闲居阅读 180评论 0 0
  • 多想,多比较,停下来,不要让迷茫一直伴随你而你却不知道。
    无限能亮阅读 219评论 0 0
  • 前言 不知你是否遇到这样的情况?千辛万苦上开发了一个版本,好不容易上线了,突然发现了一个严重bug需要进行紧急修复...
    带心情去旅行阅读 13,531评论 81 114
  • 我辈岂是蓬蒿人,怎奈往昔失落魂。 八十载前金陵难,脱劫今存仅百人。 屠刀扑粉血仍温,书本暧昧无胆认。 今日国祭传愤...
    轮回苦行僧阅读 214评论 0 0