Python基础知识 第九章 类

本系列笔记面向没有任何Python基础的读者。笔记的主要内容和代码来源于《Python编程从入门到实践》,欢迎大家讨论和指出笔记中的问题。

前言

类是Python面向对象编程的重要内容,其主要功能就是把数据与功能绑定在一起。创建新类就是创建新的对象类型,从而创建该类型的新实例 。类实例支持维持自身状态的属性,还支持(由类定义的)修改自身状态的方法。本篇笔记将通过几个例子帮助读者快速了解Python类的使用方法

9.1 创建和使用类

面向对象编程的核心概念就是创建和操作对象来完成一系列动作,其中涉及到对象这一组重要的概念。简而言之,对象(object)是具体的实例,比如柴犬、柯基、哈士奇等,他们有自己独特的品种、性别、毛发颜色等属性,可以进行吃饭、睡觉(涩涩)等行为。而类(class)是抽象的概括,比如柴犬、柯基、哈士奇都可以归为“狗”这一类别,而他们都有一些共同的属性和行为,当我们把这些属性和行为概括起来,就形成了“类”。

下面我们用一个Dog类来说明如何在Python中创建类。

dog.py

class Dog():
    """A simple attempt to model a dog."""
    
    def __init__(self, name, age):
        """Initialize name and age attributes."""
        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!")
        

my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)

print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
my_dog.sit()

print("\nMy dog's name is " + your_dog.name.title() + ".")
print("My dog is " + str(your_dog.age) + " years old.")
your_dog.sit()

1. 创建类

类的名称首字母是大写,从空白创建类的话,类定义中的括号是空的

2. 创建方法

方法 __init()__

类中的函数统称为方法,__init()__在根据Dog类创建实例时都会自动运行。该方法包含3个形参:self, name, age。其中self是必不可少的,并且要位于最前面,当Python调用__init()__方法创建Dog实例时,将自动传入实参self,它是一个指向实例本身的引用,能让实例访问类中的属性和方法。

self为前缀的变量都可以供类中的所有方法使用,并且可以通过类的任何实例来访问这些变量。self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例,这样的可以通过实例访问的变量称为属性

其他的两个方法只有一个形参self

3. 创建实例

my_dog = Dog('willie', 6),实参是“willie”和“6”,方法__init()__创建一个表示特定小狗的示例,并参数设置nameage,并未显式地包含return语句,但是会返回这条小狗的实例。

实例的命名规则:用首字母大写的名称指类,小写字母的名称是根据类创建的实例

4. 访问属性

使用句点表示法访问实例的属性 my_dog.name,找到实例my_dog,再查找与这个实例相关联的属性name。在Dog类中引用这个属性时,使用的是self.name

5. 调用方法

使用句点表示法调用方法my_dog.sit()

6. 创建多个实例

可以根据需要创建任意数量的实例

9.2 使用类和实例

当我们创建了类之后,可以对它的属性、方法进行一定的修改来让这个类拥有更多功能。

car.py

"""A class that can be used to represent a car."""

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
        
    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.")
        
    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!")
    
    def increment_odometer(self, miles):
        """Add the given amount to the odometer reading."""
        self.odometer_reading += miles

1. 给属性指定默认值

类中的每个属性都必须有初始值,可以在方法__init()__内指定初始值,在括号内设置形式参数,如果没有在创建实例时设置,则会用默认的形式参数

2. 修改属性的值

(1)直接修改属性的值

通过实例直接访问并进行修改:my_car.odometer_reading = 23

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

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

该方法可以接受一个里程值,储存到相应变量中,并且增加了一个禁止回调的功能

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

def increment_odometer(self, miles):
        """Add the given amount to the odometer reading."""
        self.odometer_reading += miles

该方法接受一个值可以修改属性

9.3 继承

一个类继承另一个类时,将自动获得另一个类的所有属性和方法,被继承的类称为父类,而新类被称为子类

electric_car.py

from car import Car

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.")  
        
    def get_range(self):
        """Print a statement about the range this battery provides."""
        if self.battery_size == 60:
            range = 140
        elif self.battery_size == 85:
            range = 185
            
        message = "This car can go approximately " + str(range)
        message += " miles on a full charge."
        print(message)
    
        
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 = Battery()

1. 子类继承父类的方法和属性

子类的__init()方法

class ElectricCar(Car):
  
    def __init__(self, manufacturer, model, year):
        super().__init__(manufacturer, model, year)

super()函数将子类与父类的所有属性关联起来,父类也称超类(superclass)。

2. 子类定义新的方法和属性

和父类添加方法和属性的过程一样,没有限制。

3. 重写父类的方法

在子类中定义一个与要重写的父类方法名称相同的方法

4. 将实例用作属性

将大型类拆分成多个协同工作的小类,比如在电动车类中增加电池类,将大类进行剖分,例如Battery()类。在ElectricCar类中,添加一个self.battery的属性可以在电动车类中创建一个Battery实例,并储存在self.battery属性中,每次方法被调用时都会创建一个电池实例,当需要使用电池实例的属性时,调用:my_tesla.battery.describe_battery()

9.4 导入类

通过前面几个小节,我们已经知道了怎样创建以及使用类。那如果我们写好了一个类,想要把它用在其他的文件中的时候,就需要用到导入类的技巧。导入类是模块化编程的一个重要知识点。

1. 导入单个类

在文档的开头添加注释来增加模块级文档字符串,使用import语句打开模块并导入:

from car import Car

2. 在一个模块中存储多个类

在模块中存储多个类,通过import导入模块中不同的类

3. 从一个模块中导入多个类

用逗号分隔各个类

from car import Car. ElectricCar

4.导入整个模块

不使用from来导入整个模块,再用句点表示法访问需要的类(注意句点是一定需要的)

import car
my_beetle = car.Car('volkswagen', 'beetle'. 2016)

5. 导入模块中的所有类

使用星号表示所有类,但是不推荐使用,可能会重名导致错误

from car import *

6. 在一个模块中导入另一个模块

当模块分散程度比较高时,在模块中使用import语句导入另一个模块。

9.5 Python标准库

Python为我们提供了很多可以直接使用的库,通过上面导入类的方法,可以将他们导入到自己的程序中。

from collections import OrderedDict

favorite_languages = OrderedDict()

favorite_languages['jen'] = 'python'
favorite_languages['sarah'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'python'

for name, language in favorite_languages.items():
    print(name.title() + "'s favorite language is " +
        language.title() + ".")

模块Collections中的OrderedDict可以用来创建有序字典,并储存在变量中。

9.6 类编码风格

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

对于每个类,都应紧跟在类定义后面包含一个文档字符串,简要的描写类的功能,并遵循编写函数的文档字符串采用的格式约定。每个模块都应包含一个文档字符串

可以用空行来组织代码:在类中使用一个空行来分隔方法;在模块中用两个空行来分隔类

需要同时导入标准库和自己编写的模块时,先编写导入标准库的import语句,在添加一个空行,导入自己编写的模块语句

代码总结

my_car.py 创建汽车实例

from car import Car

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

my_new_car.odometer_reading = 23
my_new_car.read_odometer()

my_cars.py 创建多个汽车实例

from car import Car
from electric_car import ElectricCar

my_beetle = Car('volkswagen', 'beetle', 2015)
print(my_beetle.get_descriptive_name())

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

python通过命名的起始处下划线来区分是private变量,protect变量还是public变量。

权限名称权限控制起始标志
public可见 外部可以访问无 _
protect不可见 外部可以访问_(单下划线)
private不可见 不可访问__ (双下划线)
class TestIsVisible(object):
    def __init__(self, visible, invisible, non_know):
        self.visible = visible
        self.__invisible = invisible
        self._visible = non_know

    def hello_world(self):
        dic = dict()
        dic["hello"] = "world!"
        print dic

    def __hello_china(self):
        dic = dict()
        dic["hello"] = "china"
        print dic


if __name__ == '__main__':
    visible_object = TestIsVisible("can see", "can not see", "non know if visible")
    print visible_object.visible
    print visible_object._visible
    print visible_object.__dict__
    print dir(visible_object)
    print visible_object.__invisible        
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Noobfurid

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

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

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

打赏作者

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

抵扣说明:

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

余额充值