使用 Python 迈出第一步 Python 中面向对象的编程
简要
编写第一批 Python 代码存储和操作数据以修改其类型和外观执行代码库中提供的内置功能向代码添加逻辑以实现复杂的业务功能
什么是 Python
程序是一组执行计算任务的指令。 这些指令被编译成计算机可以理解的格式。 编译后的指令由用户启动或运行。 用户一词既可以指人,也可以指另一个程序
编程是指为计算机编写指令以创建应用或脚本的行为。 有些人使用诸如编码或开发之类的不同术语来描述编程编程语言(例如 Python)可用于编写希望计算机执行的指令编程语言的语法包括关键字、运算符和语法规则。 运算符是特殊字符,例如括号和等号。 一行看似简单的 Python 代码可能遵循十几种不同的语法规则,并使用几种不同的运算符编写完源代码后,通常会使用一个称为_编译器_的特殊程序。 该程序可将源代码转换为计算机 CPU 可以运行的格式Python 具有编译器。 但是,该编译器不会将源代码直接转换为计算机可以理解的格式, 而是以特殊格式生成 Python 解释器可以解释和运行的代码解释器是运行每个指令的程序。 它跟踪 RAM 中值的存储位置。 解释器还知道如何与文件系统或网络等外部资源进行交互每次运行程序时,都会重新编译其 Python 源代码新程序的生成遵循一系列可预测的操作:
分析需求设计解决方案编写代码测试代码部署代码维护代码
第一个 Python 程序
编写 Python 代码是一项关于精确度的练习。 键入代码时,请使用正确的拼写、大写和符号使用 print 函数通过命令行或终端界面在输出中显示文本信息文本字符串是要在程序中完全按照所编写的形式使用的单个字符的字符串。 你可以通过使用一对引号或一对单引号来定义文本字符串借助 Visual Studio Code,可以轻松地创建代码文件、保存工作,然后通过选择绿色箭头图标来运行代码如果代码包含无效语法,则 Python 编译器会停止执行并显示错误。 通过使用编译器提供的线索,可以修复错误并重试保存代码文件时,Visual Studio Code 会分析代码并添加视觉线索,以帮助你在尝试运行程序前发现潜在错误使用数字符号 (#) 注释掉代码行或添加简短注释。 特定行中数字符号 (#) 之后的所有内容都会被编译器忽略,并且不会执行使用 input 函数检索最终用户的键盘输入变量是指向存储在计算机内存中的值的友好指针通过选择尚未在程序中使用且不是 Python 保留关键字之一的名称来创建新变量使用加号 (+) 符号来连接两个字符串,以创建新的字符串值关键字是属于编程语言一部分的命令,用于执行某些特殊函数运算符是属于编程语言一部分的符号,用于执行某些特殊运算函数是在软件系统中执行单个任务的代码的集合Python 标准库包含数百个分散在数十个模块中的函数,为所有开发人员提供通用功能。 其他第三方库还包含用于扩展编程语言功能的其他功能选择合适的变量名称,以提高代码的可读性如果有助于提高代码的可读性,请选择引入临时变量。 使用最佳判断并优化可读性若要对数据执行数学运算,必须先将其转换为数值数据类型。 如果你有一个表示整数的字符串值,并且要执行数学运算,则可以使用 int() 函数将该值转换为整数如果尝试使用 int() 将字符串转换为整数,但该字符串不是可以转换的值(例如姓名),则最终用户将遇到运行时错误。 如果程序员没有事先预见数据问题或其他潜在逻辑问题,则会发生运行时错误与数值数据类型配合使用时,加号 (+) 符号执行加法运算你可以调用某个函数并将其返回值传递给另一个函数。使用 str() 函数将数字值转换为字符串
卡路里计算
print("Today's date?")
date = input()
print("Breakfast calories?")
breakfast = int(input())
print("Lunch calories?")
lunch = int(input())
print("Dinner calories?")
dinner = int(input())
print("Snack calories?")
snack = int(input())
total = breakfast + lunch + dinner + snack
print("Calorie content for " + date + ": " + str(total))
使用 if…elif…else 语句对代码执行进行分支
使用 if 语句计算布尔表达式。 如果表达式的计算结果为 True,则 Python 解释器会运行 if 语句下面的代码块。 否则,它会被忽略代码块是一个或多个缩进代码行。 代码块属于 if 语句,根据布尔表达式的计算结果来运行或忽略。 意外缩进(或未缩进)代码行无疑会影响代码的运行方式,甚至可能会生成错误。 所有缩进都必须使用相同数量的空格字符,否则 Python 解释器会引发错误如果要执行仅当布尔表达式的计算结果为 False 时才相关的代码,请添加可选的 else 语句。 否则,它会被忽略在 if 语句后面添加一个可选的 elif(但是如果退出,则是在 else 语句前面)来计算第二个和后续布尔表达式。 与 if 语句一样,如果布尔表达式的计算结果为 True,则它下面的缩进代码块会运行。 否则,它会被忽略将 if 语句与一个或多个 elif 语句和 else 语句一起使用时,一旦满足布尔表达式,便不会计算任何其他语句。 因此,执行计算的顺序可能很重要如果需要在执行某个操作之前检查相关(但是不同)的条件,可以嵌套 if 语句使用 bool() 函数将字符串和整数转换为布尔值。 非空字符串转换为 True,而非零数字转换为 True。 字符串值 'False' 和空字符串转换为 False。 值 0 转换为 FalsePython 提供几个比较运算符来测试相等性、不等性以及大于还是小于Python 还提供几个逻辑运算符用于确保一个或两个布尔表达式为 True。 它还提供了 not 运算符,以确保布尔表达式的计算结果都为 False
基于输入执行分支
value = input('Would you like to continue? ')
if value == 'y' or value == 'yes':
print('Continuing ...')
print('Complete!')
elif value == 'n' or value == 'no':
print('Exiting')
else:
print('Please try again and respond with yes or no.')
对字符串进行操作和设置格式
可以使用一组单引号或双引号符号定义文本字符串可以添加转义序列以在字符串中使用特殊字符,例如单引号转义序列 (\')、双引号转义序列 (\")、换行符转义序列 (\n) 或制表符转义序列 (\t)可以通过将 r 字符作为前缀来打印字符串的原始输出可以使用一组三个单引号字符 (''') 或一组三个双引号字符 (""") 来定义多行逐字字符串print() 函数可以串联作为参数发送到函数中的可变数量的字符串。 可以指定要分隔每个参数的字符以及结束字符Python 提供许多帮助程序函数来设置字符串格式或修改其内容如果需要修改字符串,请在开始编写代码以操作字符串之前,检查是否可以使用已存在的函数可在 Python 文档中花费一些时间,或在线搜索正确的帮助程序方法以实现所需结果format() 函数使你可以定义格式字符串(实质上是模板)。 这种字符串包含一系列替换字段,它们会替换为传入函数中的参数新的格式字符串文本(或 f 字符串)可减少 format() 方法的击键。 这使你可以在替换字段中使用变量或表达式格式说明符是一种紧凑型语法,使你可以对数字、日期和百分比设置格式,以及设置对齐和间距
对字符串设置格式
first_value = ' FIRST challenge '
second_value = '- second challenge -'
third_value = 'tH IR D-C HALLE NGE'
fourth_value = 'fourth'
fifth_value = 'fifth'
sixth_value = 'sixth'
# First challenge
first_value = first_value.strip()
first_value = first_value.lower()
first_value = first_value.title()
first_value = f'{first_value:^30}'
# Second challenge
second_value = second_value.replace('-', '')
second_value = second_value.strip()
second_value = second_value.capitalize()
# Third challenge
third_value = third_value.replace(' ', '')
third_value = third_value.replace('-', ' ')
third_value = third_value.swapcase()
third_value = f'{third_value:>30}'
print(first_value)
print(second_value)
print(third_value)
# Fourth challenge - use only the print() function (no f-strings)
print(fourth_value, fifth_value, sixth_value, sep='#', end='!')
# Fifth challenge - use only a single print() function. Create tabs and new lines using f-strings.
print(f'\n\t{fourth_value}\n\t{fifth_value}\n\t{sixth_value}')
对数值数据执行数学运算
type() 函数返回指定值的数据类型。instanceof() 函数可用于检查某个值是否为指定数据类型的实例float 数据类型用于包含小数值的数值,这些小数值由小数点后的数字表示值具有数据类型,变量没有。 变量仅指向值,它可以指向任何数据类型的任何值isnumeric() 可用于检查能否将值转换为 int 或 floatisnumeric() 函数是帮助程序函数的一个示例,因为它支持使用 str 等数据类型。 将使用成员访问器运算符点字符 (.) 访问这类函数使用 exit() 函数立即结束程序的执行有时,可以使用逻辑 or 运算符来减少实现门控检查所需编写的代码量帮助程序函数可对指定类型的值进行操作,并提供一些有用的实用工具,让你可以对属于该数据类型的值执行一些常见操作每种数据类型都支持一些帮助程序函数。 你已经粗略了解了几个 str 帮助程序函数,这些函数可帮助你了解字符串值的内容
函数用途
isalnum()确保字符串没有特殊字符,例如 %、$、#、@ 或 !。isalpha()确保字符串仅包含字母。isdecimal()确保字符串仅包含十进制值(数字)。istitle()确保字符串遵循大写规则(就像在句子中一样)。isupper()确保字符串仅包含大写字母。islower()确保字符串仅包含小写字母。
运算符是用于对一个或多个操作数(文本或变量值等)执行运算的迷你快捷方式函数内置数学运算符可满足大多数常见需求。 Python 标准库中的数学模块解决了更高级的数学运算。 其他第三方开源库涵盖了数据科学、数据可视化和机器学习所需的各种功能Python 中的数学运算顺序遵循 PEMDAS 的规则将 float 类型的值转换为 int 类型的值时,小数点后的值会被截断并丢失。 可使用 round() 函数控制值的舍入方式某些函数是通过多个输入参数定义的。 若要将多个参数传递给函数,需在每个参数之间使用逗号 (,)。 有时,参数是可选的。 在这些情况下,函数将继续运行,但是会使用默认值或替代实现
将华氏温度转换为摄氏温度
fahrenheit = input('What is the temperature in Fahrenheit? ')
if fahrenheit.isnumeric() == False:
print('Input is not a number.')
exit()
fahrenheit = int(fahrenheit)
celsius = int((fahrenheit - 32) * 5/9)
print('Temperature in celsius is ' + str(celsius))
生成简单的计算器
print('Simple calculator!')
first_number = input('First number? ')
if first_number.isnumeric() == False:
print('Please input a number.')
exit()
operation = input('Operation? ')
second_number = input('Second number? ')
if second_number.isnumeric() == False:
print('Please input a number.')
exit()
first_number = int(first_number)
second_number = int(second_number)
result = 0
if operation == '+':
result = first_number + second_number
label = 'sum'
elif operation == '-':
result = first_number - second_number
label = 'difference'
elif operation == '*':
result = first_number * second_number
label = 'product'
elif operation == '/':
result = first_number / second_number
label = 'quotient'
elif operation == '**':
result = first_number ** second_number
label = 'exponent'
elif operation == '%':
result = first_number % second_number
label = 'modulus'
else:
print('Operation not recognized.')
exit()
print(label + ' of ' + str(first_number) + ' ' + operation + ' ' + str(second_number) + ' equals ' + str(result))
导入标准库模块以添加 Python 编程的功能
模块是一个文件,其中包含实现某种功能的函数。 Python 标准库由包含数千个函数的 200 多个模块组成一些重要的常用函数直接内置在 Python 编译器和解释器中必须使用 import 语句向 Python 编译器告知 Python 标准库的哪些模块包含将在代码中使用的函数、类型、服务等在线搜索是一种有效方法,可从 Python 标准库(和其他第三方包)中发现可组合在一起来解决你所面临的编程问题的模块和函数使用 import 语句可在程序中包含来自 Python 标准库的包。 模块的所有功能都可以通过使用成员访问运算符 . 来使用在 Visual Studio Code 中,Intellisense 功能可在键入成员访问运算符之后显示可用的成员(函数、常数和服务)使用 import ... as 语句可创建模块的别名(如果它有助于描述其在软件系统中的角色)random 包提供了一种生成随机值的方式。 当我们在即将到来的 Microsoft Learn 模块中构建更多有趣的代码示例时,这将十分方便访问 PyPI 以查找满足某些编程需求的候选包,而不是尝试自己构建代码逻辑。 使用 PyPI 包文档中的信息安装包并在程序中使用包的功能使用 pip install 命令在本地安装包及其所有依赖项使用命令pip freeze 可以查看当前已安装的包及其版本号
使用 while 语句循环访问代码块
使用 while 语句可以创建循环结构,该结构会持续循环遍历代码块,直到布尔表达式的计算结果为 False添加 break 语句,以便在布尔表达式的计算结果为 False 之前提前退出代码块添加 else 语句,以提供在 while 语句的布尔表达式计算结果为 False 之后运行的另一个代码块。添加 continue 语句,以跳过代码块的其余部分,并将执行路径重新设置为布尔表达式新的赋值运算符 += 和 -= 可简化递增和递减运算
运算符用途
=赋值+=执行加法,然后赋值-=执行减法,然后赋值*=执行乘法,然后赋值/=执行除法,然后赋值%=获取模数,然后赋值**=执行指数运算,然后赋值//=执行向下取整除运算,然后赋值
数字猜测
import random
value = random.randint(1, 10)
count = 0
guess = 0
print('Guess a number between 1 and 10')
while guess != value:
count += 1
guess = input(f'Enter guess #{count}: ')
if guess.isnumeric():
guess = int(guess)
else:
print('Numbers only, please!')
continue
if guess > value:
print('Your guess is too high, try again!')
elif guess < value:
print('Your guess is too low, try again!')
else:
print(f'You guessed it in {count} tries!')
使用 Python 列表管理数据序列
列表是用于在程序中收集相关数据的数据结构。 数据可以属于任何类型。 但元素通常属于相同的数据类型,因为它们在程序中的用途类似使用方括号创建列表。 使用逗号分隔每个项使用方括号和从零开始的索引访问列表中的单个元素。 使用索引 0 访问列表中的第一项。 使用索引 -1 访问列表中的最后一项。 使用其他负数作为索引来访问相对于列表末尾的项使用方括号和冒号创建切片。 冒号将切片的开头(在左侧)和切片的结尾(在右侧)分隔开来使用帮助程序函数(如 pop()、append()、remove()、extend() 和 clear())更改列表中的项使用 in 和 not in 关键字作为布尔表达式的一部分来测试值是否是列表的一部分使用 for 语句循环访问列表中的所有项。 还可使用该语句执行一个代码块,将当前项置于范围内,以便在代码块的逻辑中进行检查使用 continue 语句跳过剩余代码块逻辑,并继续到 for 语句分配的下一个列表项使用 break 语句提前中断 for 语句使用 else 语句创建在使用 for 语句循环访问列表中的所有项之后执行的代码块嵌套 for 语句,以创建两个列表的每个组合的列表使用 random 模块的 choice() 和 choices() 函数分别从列表中选择一个或多个项
发牌
import random
suits = ["Hearts", "Spades", "Clubs", "Diamonds"]
ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"]
deck = []
for suit in suits:
for rank in ranks:
deck.append(f'{rank} of {suit}')
print(f'There are {len(deck)} cards in the deck.')
print('Dealing ...')
hand = []
while len(hand) < 5:
card = random.choice(deck)
deck.remove(card)
hand.append(card)
print(f'There are {len(deck)} cards in the deck.')
print('Player has the following cards in their hand:')
print(hand)
在 Python 中使用函数创建可重用功能
函数是具有名称的代码块。 你可以定义自己的函数,并将其用作模块化和可重用性的单位。 可以将一个函数视为一项责任。 如果一个函数开始执行多个作业,则可能应该拆分该函数def 关键字定义一个函数。 使用所学的变量命名规则为函数创建名称。 使用括号定义输入参数一个函数具有零个或多个输入参数。 使用逗号分隔输入参数。 除非提供可选的默认值,否则参数是必需的。None 关键字指示变量的值不确定或未知作用域指值在函数代码块内部和外部的可见性。 函数有自己的专用作用域,该作用域对这些函数外部的代码隐藏你可以定义使用任意参数列表的函数。 列表使调用方可以传入任意数量的参数。 在前面的示例中,args 输入参数将条目作为 tuple 值进行管理你可以定义使用关键字或命名参数的函数。 调用方可以传入任意数量的命名参数。 在前面的示例中,kwargs 输入参数将条目作为 dict 值进行管理创建模块,以通过模块化方式分隔可重用代码。 Python 模块是代码文件。 通过将函数置于模块中,可以使该代码在程序内部和外部的其他代码文件中可用使用 import 语句访问模块的函数
填充缺失的函数
Define
def process_numbers(unprocessed_list):
processed_list = []
if isinstance(unprocessed_list, list) == False:
return processed_list
for item in unprocessed_list:
if isinstance(item, int):
processed_list.append(item)
elif isinstance(item, str):
if item.isnumeric():
converted_item = int(item)
processed_list.append(converted_item)
processed_list.sort()
return processed_list
def process_names(unprocessed_list):
processed_list = []
if isinstance(unprocessed_list, list) == False:
return processed_list
for item in unprocessed_list:
if isinstance(item, str):
if item.isnumeric() == False:
processed_list.append(item)
processed_list.sort()
return processed_list
保存为processor.py
import processor
my_list = [5, 'Dan', '4', 7, 'Steve', 'Amy', 'Rhonda', 4, '9', 'Jill', 7, 'Kim']
my_bad_list = 5
numbers = processor.process_numbers(my_list)
print(numbers)
names = processor.process_names(my_list)
print(names)
numbers = processor.process_numbers(my_bad_list)
print(numbers)
names = processor.process_names(my_bad_list)
print(names)
Python 中面向对象的编程
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。**类变量:**类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。**数据成员:**类变量或者实例变量, 用于处理类及其实例对象的相关的数据。**方法重写:**如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。**局部变量:**定义在方法中的变量,只作用于当前实例的类。
**实例变量:**在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。**继承:**即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。**实例化:**创建一个类的实例,类的具体对象。**方法:**类中定义的函数。**对象:**通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
面向对象的编程 (OOP)
属性。 属性定义特征,例如人物的姓名或头发的颜色方法。 方法指示对象执行任务,例如呈现数据库中的照片或记录信息事件。 事件在对象发生某些事情时触发,例如,发现失踪人员时
类与对象
对象将代码和数据组合到一个实体中,以便你可以将它们作为一个整体处理对象的基础是类,类定义对象的属性、方法和事件Python 类不包括对事件的本机支持Python 中的一切都是对象。 当你创建变量并为赋值时,Python 会创建内置类的实例Python 具有多个内置类(包括 int、float、bool 和 str),但你也可以定义自己的类定义自己的类是 OOP 的主要目标你创建的每个 Python 类都以 class 一词开头。 类需要名称,它还需要执行一些操作
属性
属性保存定义对象的数据属性有两种形式:类属性和实例属性类属性是适用于类的所有实例的属性,而不是适用于单个实例(从类创建的对象)的属性。 类属性的有趣之处在于,无需实例化类即可访问它们。 类属性始终可用实例属性是针对所创建的每个对象“实例化”的属性。 person 类可能具有保存人员姓名的 name 属性。 name 必须是实例属性,以便为每个 person 分配不同的姓名
添加属性
pip install sklearn
from sklearn.datasets import fetch_olivetti_faces
import datetime
# Load the dataset
faces = fetch_olivetti_faces()
# Prove that the dataset was loaded
print(faces.data.shape)
class Person:
def __init__(self, name, photo, date_of_birth):
self.name = name
self.photo = photo
self.dob = date_of_birth
aPerson = Person("Adam", faces.images[0], datetime.datetime(1990, 9, 16))
print(aPerson.name)
方法
from sklearn.datasets import fetch_olivetti_faces
import datetime
# Load the dataset
faces = fetch_olivetti_faces()
# Prove that the dataset was loaded
print(faces.data.shape)
class Person:
def __str__(self):
return self.name + ', age ' + str(self.get_age())
def __init__(self, name, photo, date_of_birth):
self.name = name
self.photo = photo
self.dob = date_of_birth
def get_age(self):
return int((datetime.datetime.now() - self.dob).days / 365.25)
aPerson = Person("Adam", faces.images[0], datetime.datetime(1990, 9, 16))
print(str(aPerson.get_age()))
print(str(aPerson))
print(aPerson.__str__())
print(aPerson)
继承
继承也称为子类化,是 OOP 的基本原则之一你可以使用继承定义继承其他类的属性和方法的新类,继承可促进代码重用
from sklearn.datasets import fetch_olivetti_faces
import datetime
# Load the dataset
faces = fetch_olivetti_faces()
# Prove that the dataset was loaded
print(faces.data.shape)
class Person:
def __str__(self):
return self.name + ', age ' + str(self.get_age())
def __init__(self, name, photo, date_of_birth):
self.name = name
self.photo = photo
self.dob = date_of_birth
def get_age(self):
return int((datetime.datetime.now() - self.dob).days / 365.25)
class MissingPerson(Person):
def __init__(self, name, photo, date_of_birth, date_missing):
# Construct the base object
Person.__init__(self, name, photo, date_of_birth)
# Add a missing_since attribute
self.missing_since = date_missing
# Add a get_years_missing() method
def get_years_missing(self):
return int((datetime.datetime.now() - self.missing_since).days / 365.25)
class MissingSKPerson(MissingPerson):
def __init__(self, name, photo, date_of_birth, date_missing):
MissingPerson.__init__(self, name, photo, date_of_birth, date_missing)
# Override the get_age() method
def get_age(self):
return super().get_age() + 1
date_birth = datetime.datetime(1990, 9, 16)
date_missing = datetime.datetime(2016, 1, 1)
face = faces.images[0]
name = "Adam"
aPerson = Person(name, face, date_birth)
print(str(aPerson.get_age()))
aPerson = MissingPerson(name, face, date_birth, date_missing)
print(str(aPerson.get_age()))
aPerson = MissingSKPerson(name, face, date_birth, date_missing)
print(str(aPerson.get_age()))
class AnonymousPerson(Person):
def __init__(self, photo, date_of_birth):
Person.__init__(self, '', photo, date_of_birth)
delattr(self, 'name')
aPerson = AnonymousPerson(faces.images[0], datetime.datetime(1990, 9, 16))