第9章 类

1 类概述

Python是面向对象编程语言。面向对象编程(OOP)是一种方法学,即做事的方法。编写类时,程序员定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。

类是一个对象的蓝图。类不能做任何事,因为它是一个蓝图。只有在运行时实例化对象的时候,对象才会存在。所以,开发者在编写类代码时,它只是一个类的定义,而不是一个对象。类的函数也叫作方法,类的变量通常作为属性来访问。

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hi(self):
        print("Hi, my name is {}, and I'm {}".format(self.name, self.age))


# class instance 类的实例
someone = People(name='steve', age=20)
print(someone.name)
print(someone.age)
someone.say_hi()

当创建一个对象的时候,类实例化为该对象。

使用面向对象编程可模拟显示情景。

  • 根据类来创建对象被称为实例化
  • 在Python中,首字母大写的名称指的是类。
  • 类中的函数被称为方法

每个定义行末,都必须有一个冒号。

1.1 私有属性和受保护属性

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        # 受保护属性,类内外均可使用
        self._protect_var = 10
        # 私有属性,只能在类内部才能访问(其实在类内部重命名了)
        self.__private_var = 10

    def say_hi(self):
        print("Hi, my name is {}, and I'm {}".format(self.name, self.age))

    def set_var(self, var):
        self.__private_var = var

    def get_var(self):
        return self.__private_var


# class instance 类的实例
someone = People(name='steve', age=20)
someone._protect_var = 30
print(someone._People__private_var)
print(dir(someone))

1.2 类的property

class People:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def name(self):
        return self.__name

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        self.__age = age

    @name.setter
    def name(self, name):
        self.__name = name


someone = People(name='steve', age=30)
print(someone.name)
someone.name = 'steve jobs'
print(someone.name)

2 方法__init__()

方法__init__()是一个特殊的方法,即类的构造函数。每当我们根据类创建新实例时,Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。

  • 形参self必不可少,还必须位于其他形参前面。当Python调用这个方法__init__()创建类实例时,将自动传入实参self。每个与类相关联的方法调用都自动传入实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
  • 以self为前缀的变量都可供类中的所有方法使用,程序员可通过类的任何实例来访问这些变量。
  • 通过实例访问的变量称为属性。

关键字self描述当前的类,这和其在C++中的作用是相同的。所有类的变量前面必须有一个self,以便可以认出这是类的成员,否则,它们将会被当做局部变量

3 访问属性

要访问实例的属性,可使用句点表示法。

句点表示法在Python中很常见,这种语法演示了Python如何获悉属性的值。Python先找到实例,再查找与这个实例相关联的属性。

4 调用方法

要调用方法,可指定实例的名称和要调用的党发,并用句点分隔它们。

5 创建多个实例

可按需求根据类创建任意数量的实例。一个独立的实例,都有自己的一组属性,能够执行相同的操作。

程序员可按需求根据一个类创建任意数量的实例,条件是将每个实例都存储在不同的变量中,或占用列表或字典的不同位置。

6 使用类和实例

程序员可以修改实例的属性,也可以编写方法以特定的方式来进行修改。

6.1 给属性指定默认值

类中的每个属性都必须有初始值,例如0或者空字符串。

设置默认值时,在方法__init__()内指定初始值,无需包含初始值的形参。

6.1.1 类的属性和实例属性

class Student:

    count = 0

    def __init__(self, name):
        Student.count += 1
        self.name = name


s1 = Student('A')
s2 = Student('B')
s3 = Student('C')
print(Student.count)

6.1.2 类方法和实例方法

class People:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hi(self):
        """实例的方法"""
        print("Hi, my name is {}, and I'm {}".format(self.name, self.age))

    @classmethod
    def test_0(cls):
        print("这是一个类方法。")
        cls.test_1()

    @staticmethod
    def test_1():
        print("这是一个静态方法。")


someone = People(name='Steve Jobs', age=28)
someone.say_hi()
someone.test_0()
someone.test_1()
People.test_0()
People.test_1()

6.2 修改属性的值

6.2.1 直接修改属性的值

要修改属性的值,最简单的方法是通过实例直接访问。

6.2.2 通过方法修改属性的值

无需直接访问属性,可将值传递给一个方法,由它在内部更新。

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

将属性值递增到特定的值,而不是将设置为全新的值。

7 继承

一个类继承另一个类时,它将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。子类继承了其弗雷的所有属性和方法,同时还可以定义自己的属性和方法。

此外,Python支持多继承,即一个子类可以继承多个父类或基类。只要每个父类中的变量和方法与其他变量和方法不冲突,新的子类可以访问它们。但是如果有任何冲突,来自父类的冲突变量和方法在继承顺序中具有优先性。

当一个Python类继承自一个基类,父类的所有变量和方法都是可用的。变量可以使用,方法可以覆盖。

当设计多继承时,当共享相同的变量名或方法名时,必须使用父类名称,以避免混淆。

class Animal:

    def eat(self):
        print('Animal is eating.')


class Bird(Animal):

    def sing(self):
        print("Bird is singing.")

    def eat(self):
        print('Bird is eating.')


class Dog(Animal):

    def eat(self):
        print("Dog is eating.")
        
        
class Cat(Animal):
    
    def eat(self):
        print("Cat is eating.")


bird = Bird()
bird.eat()
bird.sing()
dog = Dog()
dog.eat()
animal = Animal()

7.1 子类的方法

创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。

7.1.1 super()函数

super()是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让Python调用父类的方法__init__,让子类实例包含父类的所有属性。父类也称超类。

函数super()需要两个实参,子类名和对象self。为帮助Python将父类和子类关联起来,这些实参必不可少。

7.1.2 给子类定义属性和方法

让一个类继承另一个类后,可添加区分子类和父类所需要的新属性和方法。

7.1.3 重写父类的方法

对于父类的方法,只要父类不符合子类模拟的实物行为,都可以对其重写。为此,可在子类中定义这样一个方法,即它与要重写的父类方法同名。这样Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

使用继承时,可让子类保留从父类那里继承而来的精华,并剔除需要的糟粕。

7.1.4 将实例作为属性

为类添加的细节越多,属性和方法清单越来越长。这种情况下,需要类的一部分作为一个独立的类提取出来。程序员可以将大型类拆分为多个协同工作的小类。

8 导入类

为遵循Python的总体理念,应让文件尽可能整洁。因此,Python允许将类存储在模块中,然后再主程序中导入所需的模块。

8.1 导入单个类

通过类移到一个模块中,并导入该模块,程序员依然可以使用其所有功能,但主程序文件变得整洁而易于阅读。

这让程序员将大部分逻辑存储再独立的文件中,确认类工作后,只需要专注于主程序的高级逻辑。

8.2 再一个模块中存储多个类

同一个模块中的类之间应存在某种相关性,但可根据需要再一个模块中存储任意数量的类。

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

可根据需要在程序文件中导入任意数量的类,从一个模块中导入多个类,用逗号分隔了各个类。导入必要的类,就可根据需要创建每个类的任意数量的实例。

8.4 导入整个模块

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

由于创建类实例的代码都包含类模块,因此不会与当前文件使用的任何名称发生冲突。

8.5 导入模块中的所有类

语法如下:

from module_name import *

不推荐这种导入方式。

  • 1、文件开头的import语句,就能清楚地知道程序使用了哪些类。但这种导入方式没有明确地指出程序员使用了模块的哪些类。
  • 2、这种导入的方式可能引发名称方面的错误。

从一个模块中导入很多类,最好导入整个模块。

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

当一个模块中的类依赖于另一个模块中的类,在这种情况下,可在一个模块中导入必要的类。

8.7 自定义工作流程

一开始应让代码结构尽可能简单。先在一个文件中完成所有工作,确认一切都能正常运行,在将类移动到独立的模块。

8.8 Python标准库

Python标准库是一组模块,安装的Python都包含它。

字典让程序员将信息关联起来,但它们不记录程序员添加键值对的顺序,要创建字典并记录其中的键值对添加的顺序,可使用模块collections中的OrderDict类。(其行为几乎和字典相同,区别只在于记录了键值对的添加顺序)
这是一个不错的类,其兼具列表和字典的主要优点(在将信息关联起来的同时保留原来的顺序)。当程序员开始关心显示建模时,可能发现有序字典正好满足需求。

9 类编码风格

  • 类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都都采用小写格式,并在单词之间加上下划线。
  • 对于类,都应紧跟在类定义后面包含一个文档字符串。

这种文档字符串简要表述类的功能,并遵循编写函数的文档字符串采用的格式约定。

  • 可使用空行来组织代码,,但不能滥用。在类中,可使用一个空行来分割方法;子模块中,可使用两个空行来分割类。
  • 在同时导入标准库中的模块和程序员自己编写的模块时,先编写导入标准库的import语句,在添加一个空行,然后再编写导入程序员自己编写的模块。

10 结构化编程

结构化编程(procedural programming),即在这种情况下使用的是过程和结构。过程也叫作函数。包含在一个对象中中函数,叫做方法。

当函数当做对象的一部分讨论时,使用方法这个术语而不是函数。

10.1 结构

结构是复杂的用户定义类型(UDT),它可以将许多变量包含在一起。

在电子产业中,很多软件开发工具包(SDK)任然按照结构化的方式来开发,提供函数库来控制一个电子设备(例如显卡或嵌入式系统)。

11 多态

因为多态表示为“多种形式”或“多种形状”,所以多态指具备多种形态的能力。
在类的环境中,我们可以使用具有多种形态的方法,即参数的多种不同的集合。

在Python中,开发者可以使用可选的参数来让方法具备多种功能。

12 数据隐藏(封装)

因为Python中所有内容都是共有的,所以Python不允许变量和方法声明为私有的或受保护的。

12.1 type和isinstance

a = [1, 2]
print(type(a))


class A():
    pass


a = A()
print(type(a))
print(isinstance(a, A))
x = 1
print(isinstance(x, int))
c = [1, 2]
print(isinstance(c, str))

13 if name main

python文件有两种使用的方法.一是直接作为源代码执行,二是import到其他的python文件中被调用执行。因此if name == ‘main’: 的作用就是控制这两种情况执行代码的过程,在if name == ‘main’: 下的代码只有在第一种情况下(即文件作为源代码直接执行)才会被执行,而import到其他脚本中是不会被执行的。

if __name__ == '__main__':
    print("hello, world")

动手试一试

9-1 餐馆:

class Restaurant():
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type

    def describe_restaurant(self):
        print("The name of the restaurant is " + self.restaurant_name.title() +".")
        print("The cuisine of the restaurant is " + self.cuisine_type + ".")

    def open_restaurant(self):
        print("This restaurant is open now.")


restaurant = Restaurant('which floor', 'chinese')
print(restaurant.restaurant_name)
print(restaurant.cuisine_type)
restaurant.describe_restaurant()
restaurant.open_restaurant()

9-2 三家餐馆:

class Restaurant():
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type

    def describe_restaurant(self):
        print("The name of the restaurant is " + self.restaurant_name.title() +".")
        print("The cuisine of the restaurant is " + self.cuisine_type + ".")

    def open_restaurant(self):
        print("This restaurant is open now.")


restaurant_0 = Restaurant('which floor', 'chinese')
restaurant_1 = Restaurant('cat love', 'chinese')
restaurant_2 = Restaurant('dog love', 'chinese')
restaurant_0.describe_restaurant()
restaurant_1.describe_restaurant()
restaurant_2.describe_restaurant()

9-3 用户:

class User():
    def __init__(self, first_name, last_name, location):
        self.first_name = first_name
        self.last_name = last_name
        self.location = location

    def describe_user(self):
        print("The user's first name is " + self.first_name)
        print("The user's last name is " + self.last_name)
        print("The user's location is " + self.location)

    def great_user(self):
        print(self.first_name.title() + " " + self.last_name.title() + ", hello world!")


user_0 = User('steve', 'jobs', 'china')
user_0.describe_user()
user_0.great_user()
user_1 = User('dog', 'white', 'china')
user_1.describe_user()
user_1.great_user()
user_2 = User('cat', 'mike', 'china')
user_2.describe_user()
user_2.great_user()

9-4 就餐人数:

class Restaurant():
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type
        self.number_served = 0

    def describe_restaurant(self):
        print("The name of the restaurant is " + self.restaurant_name.title() +".")
        print("The cuisine of the restaurant is " + self.cuisine_type + ".")

    def set_number_served(self, number_served):
        self.number_served = number_served

    def open_restaurant(self):
        print("This restaurant is open now.")

    def increment_number_served(self, increment_number):
        self.number_served += increment_number


restaurant = Restaurant('which floor', 'Spicy crayfish')
print("There were " + str(restaurant.number_served) + " people at the table")
restaurant.set_number_served(100)
print("There were " + str(restaurant.number_served) + " people at the table")
restaurant.increment_number_served(120)
print("There were " + str(restaurant.number_served) + " people at the table")

9-5 尝试登录次数:

class User():
    def __init__(self, first_name, last_name, location):
        self.first_name = first_name
        self.last_name = last_name
        self.location = location
        self.login_attempts = 0

    def increment_login_attempts(self):
        self.login_attempts += 1

    def reset_login_attempts(self):
        self.login_attempts = 0

    def describe_user(self):
        print("The user's first name is " + self.first_name)
        print("The user's last name is " + self.last_name)
        print("The user's location is " + self.location)

    def great_user(self):
        print(self.first_name.title() + " " + self.last_name.title() + ", hello world!")


user = User('steve', 'jobs', 'china')
print("The login attempts of the user is " + str(user.login_attempts) + ".")
user.increment_login_attempts()
user.increment_login_attempts()
print("The login attempts of the user is " + str(user.login_attempts) + ".")
user.reset_login_attempts()
print("The login attempts of the user is " + str(user.login_attempts) + ".")

9-6 冰淇淋小店:

class Restaurant():
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type

    def describe_restaurant(self):
        print("The name of the restaurant is " + self.restaurant_name.title() +".")
        print("The cuisine of the restaurant is " + self.cuisine_type + ".")

    def open_restaurant(self):
        print("This restaurant is open now.")


class IceCreamStand(Restaurant):
    def __init__(self, restaurant_name, cuisine_type):
        super().__init__(restaurant_name, cuisine_type)
        self.flavors = ['strawberry', 'banana', 'apple']

    def show_ice_cream_flavors(self):
        print(self.flavors)


shop = IceCreamStand('which floor', 'chinese')
shop.show_ice_cream_flavors()

9-7 管理员:

class User():
    def __init__(self, first_name, last_name, location):
        self.first_name = first_name
        self.last_name = last_name
        self.location = location
        self.login_attempts = 0

    def increment_login_attempts(self):
        self.login_attempts += 1

    def reset_login_attempts(self):
        self.login_attempts = 0

    def describe_user(self):
        print("The user's first name is " + self.first_name)
        print("The user's last name is " + self.last_name)
        print("The user's location is " + self.location)

    def great_user(self):
        print(self.first_name.title() + " " + self.last_name.title() + ", hello world!")


class Admin(User):
    def __init__(self, first_name, last_name, location):
        super().__init__(first_name, last_name, location)
        self.privileges = ['can add post', 'can delete post', 'can ban user']

    def show_privileges(self):
        print("Administrator rights")

admin = Admin('steve', 'jobs', 'china')
admin.show_privileges()

9-8 权限:

class User():
    def __init__(self, first_name, last_name, location):
        self.first_name = first_name
        self.last_name = last_name
        self.location = location
        self.login_attempts = 0

    def increment_login_attempts(self):
        self.login_attempts += 1

    def reset_login_attempts(self):
        self.login_attempts = 0

    def describe_user(self):
        print("The user's first name is " + self.first_name)
        print("The user's last name is " + self.last_name)
        print("The user's location is " + self.location)

    def great_user(self):
        print(self.first_name.title() + " " + self.last_name.title() + ", hello world!")


class Admin(User):
    def __init__(self, first_name, last_name, location):
        super().__init__(first_name, last_name, location)
        self.privileges = Privileges()


class Privileges():
    def __init__(self):
        self.privileges = ['can add post', 'can delete post', 'can ban user']

    def show_privileges(self):
        print("Administrator rights")


admin = Admin('steve', 'jobs', 'china')
admin.privileges.show_privileges()

9-10 导入Restaurant类:

from restaurant import Restaurant
restaurant = Restaurant('which floor', 'china')
restaurant.open_restaurant()


class Restaurant():
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type
        self.number_served = 0

    def describe_restaurant(self):
        print("The name of the restaurant is " + self.restaurant_name.title() +".")
        print("The cuisine of the restaurant is " + self.cuisine_type + ".")

    def set_number_served(self, number_served):
        self.number_served = number_served

    def open_restaurant(self):
        print("This restaurant is open now.")

    def increment_number_served(self, increment_number):
        self.number_served += increment_number

9-13 使用OrderedDict:

from collections import OrderedDict
glossary = OrderedDict()
for key, value in glossary.items():
    print(key + ": " + value)
glossary["or"] = "或者"
glossary["and"] = "并且"
glossary["break"] = "跳出当前循环"
glossary["title"] = "以首字母大写显示"
glossary["float"] = "浮点数"
for key, value in glossary.items():
    print(key + ": " + value)

9-14 骰子:

from random import randint


class Die():
    def __init__(self, side=6):
        self.side = side

    def roll_die(self):
        x = randint(1, self.side + 1)
        print(x)


die = Die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
print()
die = Die(10)
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
print()
die = Die(20)
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
die.roll_die()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值