Python 数据类型和面向对象编程详解

在本章中,我们将讨论 Python 中的数据类型和面向对象编程OOP)。我们将讨论 Python 中的数据类型,包括列表、字典、元组和集合。我们还将讨论 OOP,它的必要性,以及如何为基于 Raspberry Pi 的项目(例如,使用 OOP 控制家用电器)编写 Python 面向对象代码。我们将讨论在 Raspberry Pi Zero 项目中使用 OOP。

在 Python 中,列表是一种数据类型(其文档可在此处获得,https://docs.python.org/3.4/tutorial/datastructures.html# ),可用于按顺序存储元素。

The topics discussed in this chapter can be difficult to grasp unless used in practice. Any example that is represented using this notation: >>> indicates that it could be tested using the Python interpreter.

列表可以由字符串、对象(本章将详细讨论)或数字等组成。例如,以下是列表的示例:

    >>> sequence = [1, 2, 3, 4, 5, 6]
 >>> example_list = ['apple', 'orange', 1.0, 2.0, 3]

在前面的一组示例中,sequence列表由16之间的数字组成,example_list列表由字符串、整数和浮点数组成。列表用方括号([]表示。可以将项目添加到以逗号分隔的列表中:

    >>> type(sequence)
 <class 'list'>

由于列表是元素的有序序列,因此可以通过使用for循环遍历列表元素来获取列表元素,如下所示:

for item in sequence: 
    print("The number is ", item)

输出如下:

 The number is  1
 The number is  2
 The number is  3
 The number is  4
 The number is  5
 The number is  6

因为 Python 的循环可以遍历一系列元素,所以它获取每个元素并将其分配给item。此项打印在控制台上。

在 Python 中,可以使用dir()方法检索数据类型的属性。例如,sequence列表可用的属性可以按如下方式检索:

    >>> dir(sequence)
 ['__add__', '__class__', '__contains__', '__delattr__',
    '__delitem__', '__dir__', '__doc__', '__eq__',
    '__format__', '__ge__', '__getattribute__', '__getitem__',
    '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', 
    '__iter__', '__le__', '__len__', '__lt__', '__mul__',
    '__ne__', '__new__', '__reduce__', '__reduce_ex__',
    '__repr__', '__reversed__', '__rmul__', '__setattr__', 
    '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 
    'append', 'clear', 'copy', 'count', 'extend', 'index',
    'insert', 'pop', 'remove', 'reverse', 'sort']

这些属性允许对列表执行不同的操作。让我们详细讨论每个属性。

可以使用append()方法添加元素:

    >>> sequence.append(7)
 >>> sequence
 [1, 2, 3, 4, 5, 6, 7]

remove()方法查找元素的第一个实例(传递了一个参数)并将其从列表中删除。让我们考虑下面的例子:

       >>> sequence = [1, 1, 2, 3, 4, 7, 5, 6, 7]
 >>> sequence.remove(7)
 >>> sequence
 [1, 1, 2, 3, 4, 5, 6, 7]
  • 例 2
       >>> sequence.remove(1)
 >>> sequence
 [1, 2, 3, 4, 5, 6, 7]
  • 例 3
       >>> sequence.remove(1)
 >>> sequence
 [2, 3, 4, 5, 6, 7]

index()方法返回元素在列表中的位置:

    >>> index_list = [1, 2, 3, 4, 5, 6, 7]
 >>> index_list.index(5)
 4

在本例中,该方法返回元素5的索引。由于 Python 使用基于零的索引,即索引从 0 开始计数,因此元素5的索引为4

    random_list = [2, 2, 4, 5, 5, 5, 6, 7, 7, 8]
 >>> random_list.index(5)
 3

在本例中,该方法返回元素的第一个实例的位置。元件5位于第三个位置。

pop()方法允许从指定位置移除元素并返回:

    >>> index_list = [1, 2, 3, 4, 5, 6, 7]
 >>> index_list.pop(3)
 4
 >>> index_list
 [1, 2, 3, 5, 6, 7]

在本例中,index_list列表由17之间的数字组成。当通过传递索引位置(3)作为参数弹出第三个元素时,数字4将从列表中删除并返回。

如果没有为索引位置提供参数,则弹出并返回最后一个元素:

    >>> index_list.pop()
 7
 >>> index_list
 [1, 2, 3, 5, 6]

在本例中,最后一个元素(7)被弹出并返回。

count()方法返回元素在列表中出现的次数。例如,元素在列表中出现两次:random_list

 >>> random_list = [2, 9, 8, 4, 3, 2, 1, 7] >>> random_list.count(2) 2

insert()方法允许在列表中的特定位置添加元素。例如,让我们考虑下面的例子:

    >>> day_of_week = ['Monday', 'Tuesday', 'Thursday',
    'Friday', 'Saturday']

在列表中,Wednesday缺失。它需要定位在位置 2 的TuesdayThursday之间(Python 使用零基索引,即元素的位置/索引被计为 0、1、2 等)。可以使用 insert 添加,如下所示:

    >>> day_of_week.insert(2, 'Wednesday')
 >>> day_of_week
 ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
    'Friday', 'Saturday']

在前面的列表中,Sunday缺失。使用列表的insert属性将其插入到正确的位置。

可以使用extend()方法将两个列表组合在一起。day_of_weeksequence列表可以组合如下:

    >>> day_of_week.extend(sequence)
 >>> day_of_week
 ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    'Saturday', 1, 2, 3, 4, 5, 6]

列表也可以按如下方式组合:

    >>> [1, 2, 3] + [4, 5, 6]
 [1, 2, 3, 4, 5, 6]

也可以将列表作为元素添加到另一个列表中:

    sequence.insert(6, [1, 2, 3])
 >>> sequence
 [1, 2, 3, 4, 5, 6, [1, 2, 3]]

可以使用clear()方法删除列表中的所有元素:

    >>> sequence.clear()
 >>> sequence
 []

可以使用sort()方法对列表中的元素进行排序:

    random_list = [8, 7, 5, 2, 2, 5, 7, 5, 6, 4]
 >>> random_list.sort()
 >>> random_list
 [2, 2, 4, 5, 5, 5, 6, 7, 7, 8]

当列表由字符串集合组成时,它们将按字母顺序排序:

    >>> day_of_week = ['Monday', 'Tuesday', 'Thursday',
    'Friday', 'Saturday']
 >>> day_of_week.sort()
 >>> day_of_week
 ['Friday', 'Monday', 'Saturday', 'Thursday', 'Tuesday']

reverse()方法允许颠倒列表元素的顺序:

    >>> random_list = [8, 7, 5, 2, 2, 5, 7, 5, 6, 4]
 >>> random_list.reverse()
 >>> random_list
 [4, 6, 5, 7, 5, 2, 2, 5, 7, 8]

copy()方法允许创建列表的副本:

    >>> copy_list = random_list.copy()
 >>> copy_list
 [4, 6, 5, 7, 5, 2, 2, 5, 7, 8]

可以通过指定list_name[i]元素的索引位置来访问列表元素。例如,random_list列表的第 0 个列表元素可以按如下方式访问:

 >>> random_list = [4, 6, 5, 7, 5, 2, 2, 5, 7, 8] 
 >>> random_list[0]4>>> random_list[3]7

可以访问指定索引之间的元素。例如,可以检索索引 2 和 4 之间的所有元素:

    >>> random_list[2:5]
 [5, 7, 5]

清单的前六个要素可按如下方式查阅:

    >>> random_list[:6]
 [4, 6, 5, 7, 5, 2]

列表中的元素可以按以下相反顺序打印:

    >>> random_list[::-1]
 [8, 7, 5, 2, 2, 5, 7, 5, 6, 4]

列表中的第二个元素可以按如下方式提取:

    >>> random_list[::2]
 [4, 5, 5, 2, 7]

在跳过前两个元素后,还可以在第二个元素之后获取每一个第二个元素:

    >>> random_list[2::2]
 [5, 5, 2, 7]

可以使用in关键字检查值是否为列表的成员。例如:

 >>> random_list = [2, 1, 0, 8, 3, 1, 10, 9, 5, 4]

在此列表中,我们可以检查编号6是否为成员:

    >>> 6 in random_list
 False
 >>> 4 in random_list
 True

本练习由两部分组成。在第一部分中,我们将回顾如何构建一个包含 10 个介于010之间的随机数的列表。第二部分是对读者的挑战。执行以下步骤:

  1. 第一步是创建一个空列表。让我们创建一个名为random_list的空列表。可以按如下方式创建空列表:
       random_list = []
  1. 我们将使用 Python 的random模块(https://docs.python.org/3/library/random.html 生成随机数。为了在010之间生成随机数,我们将使用random模块中的randint()方法:
       random_number = random.randint(0,10)
  1. 让我们将生成的编号附加到列表中。此操作使用for循环重复10次:
       for index in range(0,10):
             random_number = random.randint(0, 10)
             random_list.append(random_number)
       print("The items in random_list are ")
       print(random_list)
  1. 生成的列表如下所示:
       The items in random_list are
 [2, 1, 0, 8, 3, 1, 10, 9, 5, 4]

我们讨论了生成随机数列表。下一步是进行用户输入,我们要求用户猜测介于010之间的数字。如果号码是列表中的一个成员,则会将消息Your guess is correct打印到屏幕上,否则会打印消息Sorry! Your guess is incorrect。我们把第二部分留给读者作为一个挑战。开始使用本章提供的可下载的list_generator.py代码示例。

字典(https://docs.python.org/3.4/tutorial/datastructures.html#dictionaries 是一种数据类型,是键和值对的无序集合。字典中的每个键都有一个关联的值。字典的一个例子是:

 >>> my_dict = {1: "Hello", 2: "World"}
    >>> my_dict

    {1: 'Hello', 2: 'World'}

使用大括号{}创建字典。在创建时,新成员将以以下格式添加到字典中:key: value(如上例所示)。在前面的示例中,12是键,'Hello''World'是相关值。添加到字典中的每个值都需要有一个关联的键。

字典中的元素没有顺序,即无法按添加顺序检索元素。可以通过迭代键来检索字典的值。让我们考虑下面的例子:

 >>> my_dict = {1: "Hello", 2: "World", 3: "I", 4: "am",
    5: "excited", 6: "to", 7: "learn", 8: "Python" }

有几种方法可以打印字典的键或值:

 >>> for key in my_dict: ... 

    print(my_dict[value]) 
 ... Hello World I 
 am excited to learn Python

在前面的示例中,我们迭代字典的键,并使用键my_dict[key]检索值。也可以使用字典提供的values()方法检索值:

 >>> for value in my_dict.values(): ... 

    print(value) ... Hello World I am excited to learn Python

字典的键可以是整数、字符串或元组。字典的键必须是唯一的,并且是不可变的,即创建后不能修改键。无法创建密钥的副本。如果向现有键添加新值,则最新值将存储在字典中。让我们考虑下面的例子:

  • 可以将新的键/值对添加到字典中,如下所示:
 >>> my_dict[9] = 'test' >>> my_dict {1: 'Hello', 2: 'World', 3: 'I', 4: 'am', 5: 'excited',
       6: 'to', 7: 'learn', 8: 'Python', 9: 'test'}
  • 让我们尝试创建密钥9的副本:
 >>> my_dict[9] = 'programming' >>> my_dict {1: 'Hello', 2: 'World', 3: 'I', 4: 'am', 5: 'excited',
       6: 'to', 7: 'learn', 8: 'Python', 9: 'programming'}
  • 如前一个示例所示,当我们尝试创建副本时,现有密钥的值会被修改。
  • 可以将多个值与一个键关联。例如,作为列表或字典:
 >>> my_dict = {1: "Hello", 2: "World", 3: "I", 4: "am",
      "values": [1, 2, 3,4, 5], "test": {"1": 1, "2": 2} } 

字典在解析 CSV 文件和将每一行与唯一键关联等场景中非常有用。字典还用于对 JSON 数据进行编码和解码

元组(发音类似于two pletuh ple)是一种不可变的数据类型,由逗号排序和分隔。可以按如下方式创建元组:

 >>> my_tuple = 1, 2, 3, 4, 5
 >>> my_tuple (1, 2, 3, 4, 5)

由于元组是不可变的,因此无法修改给定索引处的值:

    >>> my_tuple[1] = 3
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 TypeError: 'tuple' object does not support item assignment

元组可以由数字、字符串或列表组成。由于列表是可变的,如果列表是元组的成员,则可以对其进行修改。例如:

    >>> my_tuple = 1, 2, 3, 4, [1, 2, 4, 5]
 >>> my_tuple[4][2] = 3
 >>> my_tuple
 (1, 2, 3, 4, [1, 2, 3, 5])

元组在无法修改值的情况下特别有用。元组还用于从函数返回值。让我们考虑下面的例子:

 >>> for value in my_dict.items(): ... 

    print(value) 
 ...
 (1, 'Hello') (2, 'World') (3, 'I') (4, 'am') ('test', {'1': 1, '2': 2}) ('values', [1, 2, 3, 4, 5])

在前面的示例中,items()方法返回元组列表。

一套(https://docs.python.org/3/tutorial/datastructures.html#sets 是一个无序的不可变元素集合,没有重复条目。可以按如下方式创建一个集合:

 >>> my_set = set([1, 2, 3, 4, 5]) >>> my_set {1, 2, 3, 4, 5}

现在,让我们在此集合中添加一个重复列表:

 >>> my_set.update([1, 2, 3, 4, 5]) >>> my_set {1, 2, 3, 4, 5}

集合可避免重复条目并保存唯一条目。可以将单个元素添加到集合中,如下所示:

 >>> my_set = set([1, 2, 3, 4, 5]) >>> my_set.add(6)
 >>> my_set
 {1, 2, 3, 4, 5, 6}

集合用于测试元素在不同集合之间的成员关系。有不同的方法与成员资格测试相关。我们建议使用集合上的文档了解每种方法(运行help(my_set)以找到可用于成员资格测试的不同方法)。

OOP 是一个有助于简化代码和简化应用程序开发的概念。它在重用代码时特别有用。面向对象的代码允许对使用通信接口的传感器重用代码。例如,可以使用面向对象的代码将配备 UART 端口的所有传感器分组在一起。

OOP 的一个例子是GPIO 零库https://www.raspberrypi.org/blog/gpio-zero-a-friendly-python-api-for-physical-computing/ 前面章节中使用的。事实上,在 Python 中,一切都是一个对象。

面向对象的代码在项目中与其他人协作时特别有用。例如,您可以使用 Python 中的面向对象代码实现传感器驱动程序,并记录其用法。这使其他开发人员能够开发应用程序,而不必关注传感器接口背后的细节。OOP 为简化应用程序开发的应用程序提供了模块化。我们将回顾本章中演示 OOP 优势的一个示例。在本章中,我们将利用 OOP 为我们的项目带来模块化。

让我们开始吧!

让我们回顾一下第 10 章算术运算、循环和闪烁灯光input_test.py中的身份证示例。我们讨论了如何编写一个简单的程序来捕获和打印属于学生的信息。学生的联系信息可以按如下方式检索和存储:

name = input("What is your name? ") 
address = input("What is your address? ") 
age = input("How old are you? ")

现在,考虑一个场景,其中 10 个学生的信息必须在程序执行过程中的任何时刻被保存和检索。我们需要为用于保存学生信息的变量制定一个术语。如果我们使用 30 个不同的变量来存储属于每个学生的信息,那将是一个混乱。这就是面向对象编程真正有用的地方。

让我们使用 OOP 重写此示例以简化问题。OOP 的第一步是为对象声明一个结构。这是通过定义一个类来完成的。该类确定对象的函数。让我们编写一个 Python 类来定义 student 对象的结构。

由于我们将保存学生信息,因此该类将被称为Student。使用class关键字定义一个类,如下所示:

class Student(object):

因此,定义了一个名为Student的类。每当创建一个新对象时,Python 会在内部调用方法__init__()(下划线表示 init 方法是一个神奇的方法,也就是说,它是一个在创建对象时由 Python 调用的函数)。

此方法在类中定义:

class Student(object): 
    """A Python class to store student information""" 

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

在本例中,__init__方法的参数包括nameageaddress。这些参数称为属性。这些属性允许创建属于Student类的唯一对象。因此,在本例中,当创建Student类的实例时,属性nameageaddress是必需的参数。

让我们创建一个属于Student类的对象(也称为实例):

student1 = Student("John Doe", "123 Main Street, Newark, CA", "29")

在本例中,我们创建了一个属于名为student1Student类的对象,其中John Doe(名称)、29(年龄)和123 Main Street, Newark, CA(地址)是创建对象所需的属性。当我们通过传递必要的参数(前面在Student类的__init__()方法中声明)来创建属于Student类的对象时,会自动调用__init__()方法来初始化该对象。初始化时,与student1相关的信息存储在对象student1下。

现在,属于student1的信息可以按如下方式检索:

print(student1.name) 
print(student1.age) 
print(student1.address)

现在,让我们创建另一个名为student2的对象:

student2 = Student("Jane Doe", "123 Main Street, San Jose, CA", "27")

我们创建了两个名为student1student2的对象。每个对象的属性都可以通过student1.namestudent2.name等方式访问。在没有面向对象编程的情况下,我们将不得不创建像student1_namestudent1_agestudent1_addressstudent2_namestudent2_agestudent2_address等变量。因此,OOP 支持模块化代码。

让我们在Student类中添加一些方法来帮助检索学生的信息:

class Student(object): 
    """A Python class to store student information""" 

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

    def return_name(self): 
        """return student name""" 
        return self.name 

    def return_age(self): 
        """return student age""" 
        return self.age 

    def return_address(self): 
        """return student address""" 
        return self.address

在本例中,我们添加了三个方法,即分别返回属性nameageaddressreturn_name()return_age()return_address()。类的这些方法称为可调用属性。让我们回顾一个快速的示例,其中我们使用这些可调用属性打印对象的信息。

student1 = Student("John Doe", "29", "123 Main Street, Newark, CA") 
print(student1.return_name()) 
print(student1.return_age()) 
print(student1.return_address())

到目前为止,我们讨论了检索学生信息的方法。让我们在类中包含一个方法,该方法可以更新属于学生的信息。现在,让我们向类中添加另一个方法,该方法允许学生更新地址:

def update_address(self, address): 
    """update student address""" 
    self.address = address 
    return self.address

让我们比较一下更新地址前后student1对象的地址:

print(student1.address()) 
print(student1.update_address("234 Main Street, Newark, CA"))

这将在屏幕上打印以下输出:

    123 Main Street, Newark, CA
 234 Main Street, Newark, CA

因此,我们编写了第一个面向对象的代码,演示了模块化代码的能力。前面的代码示例可作为student_info.py与本章一起下载。

在面向对象的示例中,您可能注意到一个用三个双引号括起来的句子:

    """A Python class to store student information"""

这称为一个文档字符串。文档字符串用于记录有关类或方法的信息。文档字符串在尝试存储与方法或类的使用相关的信息时特别有用(这将在本章后面演示)。文档字符串还用于在文件开头存储与应用程序或代码示例相关的多行注释。Python 解释器忽略了文档字符串,它们旨在向其他程序员提供关于类的文档。

类似地,Python 解释器忽略任何以#符号开头的单行注释。单行注释通常用于对代码块进行特定注释。包含结构良好的注释的实践使代码可读。

例如,下面的代码片段通知读者,09之间的随机数被生成并存储在变量rand_num中:

# generate a random number between 0 and 9 
rand_num = random.randrange(0,10)

相反,不提供上下文的注释会让正在审阅代码的人感到困惑:

# Todo: Fix this later

很可能在以后重新访问代码时无法回忆起需要修复的内容。

在我们的面向对象示例中,每个方法的第一个参数都有一个名为self的参数。self指正在使用的类的实例,self关键字用作与该类实例交互的方法中的第一个参数。在上例中,self表示对象student1。这相当于初始化一个对象并按如下方式访问它:

Student(student1, "John Doe", "29", "123 Main Street, Newark, CA") 
Student.return_address(student1)

在本例中,self关键字简化了我们访问对象属性的方式。现在,让我们回顾一些例子,在这些例子中,我们使用了涉及 Raspberry Pi 的 OOP。

让我们编写一个 Python 类(tone_player.py在下载中),它播放一个音乐音调,指示 Raspberry Pi 的启动已完成。在本节中,您需要一个 USB 声卡和一个连接到 Raspberry Pi USB 集线器的扬声器。

让我们给我们班打电话TonePlayer。此类应能够控制扬声器音量,并在创建对象时播放作为参数传递的任何文件:

class TonePlayer(object): 
    """A Python class to play boot-up complete tone""" 

    def __init__(self, file_name): 
        self.file_name = file_name

在这种情况下,TonePlayer类必须播放的文件必须传递一个参数。例如:

       tone_player = TonePlayer("/home/pi/tone.wav")

我们还需要能够设置音量水平,在该音量水平下必须播放音调。让我们添加一个方法来执行相同的操作:

def set_volume(self, value): 
    """set tone sound volume""" 
    subprocess.Popen(["amixer", "set", "'PCM'", str(value)], 
    shell=False)

set_volume方法中,我们使用 Python 的subprocess模块运行 Linux 系统命令来调整声音驱动音量。

这个类最基本的方法是play命令。调用play方法时,我们需要使用 Linux 的 aplay命令播放音调声音:

def play(self):
    """play the wav file"""
    subprocess.Popen(["aplay", self.file_name], shell=False)

总而言之:

import subprocess 

class TonePlayer(object): 
    """A Python class to play boot-up complete tone""" 

    def __init__(self, file_name): 
        self.file_name = file_name 

    def set_volume(self, value): 
        """set tone sound volume""" 
        subprocess.Popen(["amixer", "set", "'PCM'", str(value)],
        shell=False) 

    def play(self): 
        """play the wav file""" 
        subprocess.Popen(["aplay", self.file_name], shell=False) 

if __name__ == "__main__": 
    tone_player = TonePlayer("/home/pi/tone.wav") 
    tone_player.set_volume(75) 
    tone_player.play()

TonePlayer类保存到您的 Raspberry Pi(保存到名为tone_player.py的文件中),并使用来自freesound等来源的音调文件 https://www.freesound.org/people/zippi1/sounds/18872/ )。将其保存到您选择的位置,然后尝试运行代码。它应该以所需的音量播放音调声音!

现在,编辑/etc/rc.local并在文件末尾添加以下行(就在exit 0行之前):

python3 /home/pi/toneplayer.py

这应该会在 Pi 启动时播放一个音调!

让我们回顾另一个示例,其中我们使用 OOP 实现了一个简单的守护进程,该守护进程在一天中的指定时间打开/关闭灯光。为了能够在预定时间执行任务,我们将使用schedule库(https://github.com/dbader/schedule 。它可以按如下方式安装:

    sudo pip3 install schedule

让我们给我们班打电话LightScheduler。它应该能够接受在给定时间打开/关闭灯的开始和结束时间。它还应提供覆盖功能,允许用户根据需要打开/关闭灯。假设该灯由动力开关 Tail II控制 http://www.powerswitchtail.com/Pages/default.aspx )。其接口如下所示:

Raspberry Pi Zero interfaced to the PowerSwitch Tail II

以下是创建的LightSchedular类:

class LightScheduler(object): 
    """A Python class to turn on/off lights""" 

    def __init__(self, start_time, stop_time): 
        self.start_time = start_time 
        self.stop_time = stop_time 
        # lamp is connected to GPIO pin2.
        self.lights = OutputDevice(2)

无论何时创建LightScheduler实例,GPIO 引脚都会初始化以控制动力开关 Tail II。现在,让我们添加打开/关闭灯光的方法:

def init_schedule(self): 
        # set the schedule 
        schedule.every().day.at(self.start_time).do(self.on) 
        schedule.every().day.at(self.stop_time).do(self.off) 

    def on(self): 
        """turn on lights""" 
        self.lights.on() 

    def off(self): 
        """turn off lights""" 
        self.lights.off()

init_schedule()方法中,作为参数传递的开始和停止时间用于初始化schedule以在指定时间打开/关闭灯。

综合起来,我们有:

import schedule 
import time 
from gpiozero import OutputDevice 

class LightScheduler(object): 
    """A Python class to turn on/off lights""" 

    def __init__(self, start_time, stop_time): 
        self.start_time = start_time 
        self.stop_time = stop_time 
        # lamp is connected to GPIO pin2.
        self.lights = OutputDevice(2) 

    def init_schedule(self): 
        # set the schedule 
        schedule.every().day.at(self.start_time).do(self.on) 
        schedule.every().day.at(self.stop_time).do(self.off) 

    def on(self): 
        """turn on lights""" 
        self.lights.on() 

    def off(self): 
        """turn off lights""" 
        self.lights.off() 

if __name__ == "__main__": 
    lamp = LightScheduler("18:30", "9:30") 
    lamp.on() 
    time.sleep(50) 
    lamp.off() 
    lamp.init_schedule() 
    while True:
        schedule.run_pending() 
        time.sleep(1)

在前面的示例中,灯光计划在下午 6:30 打开,在上午 9:30 关闭。一旦作业计划完成,程序将进入无限循环,等待任务执行。这个例子可以通过在启动时执行文件作为守护进程运行(在/etc/rc.local中添加一个名为light_scheduler.py的行)。调度作业后,它将继续作为后台守护进程运行。

This is just a basic introduction to OOP and its applications (keeping the beginner in mind). Refer to this book's website for more examples on OOP.

在本章中,我们讨论了列表和 OOP 的优点。我们以 Raspberry Pi 为中心讨论了 OOP 示例。由于本书主要面向初学者,我们决定在讨论示例时坚持 OOP 的基础知识。有些高级方面超出了本书的范围。我们让读者使用本书网站上提供的其他示例来学习高级概念。

教程来源于Github,感谢apachecn大佬的无私奉献,致敬!

技术教程推荐

Elasticsearch核心技术与实战 -〔阮一鸣〕

Go 语言项目开发实战 -〔孔令飞〕

深入浅出可观测性 -〔翁一磊〕

运维监控系统实战笔记 -〔秦晓辉〕

快速上手C++数据结构与算法 -〔王健伟〕

结构会议力 -〔李忠秋〕

结构沟通力 -〔李忠秋〕

结构思考力 · 透过结构看表达 -〔李忠秋〕

程序员职业规划手册 -〔雪梅〕