Python程序设计与算法基础教程-学习札记

  • Post author:
  • Post category:python




了解自己的工作状态,并保持持续性努力高效工作的状态。



前言



1. 声明

  1. 此系列文章是自己阅读学习江红和余青松主编的《Python程序设计与算法基础教程》的读书札记,会不定期更新。
  2. 此系列文章的目的是记录自己的学习历程,巩固Python的基础知识,博文内容来源于教程内容,主要是教程中的自己认为有价值的语法,重点的例题和习题的记录,内容所有权归江红和余青松两位著者。



2. 版本



2.1 山东青岛 2021年4月19日 Version 1




第3章 程序流程控制



3.3 循环语句



例3.12 打印九九乘法表


程序如下:

'''
1. 例3.12:打印九九乘法表-P51
   (1) 第3章-程序流程控制
       3.3 循环语句
           3.3.5 循环的嵌套

2. 2021年5月1日 星期六
'''

for i in range(1,10):
    s = ""
    for j in range(1,10):
        s = s + str.format("{0:1}*{1:1}={2:<4}",i,j,i*j)
    print(s)
    
print('****'*20)

for i in range(1,10):
    s = ""
    for j in range(1,i+1):
        s = s + str.format("{0:1}*{1:1}={2:<4}",i,j,i*j)
    print(s)
    
print('****'*20)

for i in range(1,10):
    s = ""
    for j in range(1,10):
        if j < i:
            s = s + str.format("{0:1} {1:1} {2:<4}","","","")    
        else:
            s = s + str.format("{0:1}*{1:1}={2:<4}",i,j,i*j)     
    print(s)


运行结果如下:

1*1=1   1*2=2   1*3=3   1*4=4   1*5=5   1*6=6   1*7=7   1*8=8   1*9=9   
2*1=2   2*2=4   2*3=6   2*4=8   2*5=10  2*6=12  2*7=14  2*8=16  2*9=18  
3*1=3   3*2=6   3*3=9   3*4=12  3*5=15  3*6=18  3*7=21  3*8=24  3*9=27  
4*1=4   4*2=8   4*3=12  4*4=16  4*5=20  4*6=24  4*7=28  4*8=32  4*9=36  
5*1=5   5*2=10  5*3=15  5*4=20  5*5=25  5*6=30  5*7=35  5*8=40  5*9=45  
6*1=6   6*2=12  6*3=18  6*4=24  6*5=30  6*6=36  6*7=42  6*8=48  6*9=54  
7*1=7   7*2=14  7*3=21  7*4=28  7*5=35  7*6=42  7*7=49  7*8=56  7*9=63  
8*1=8   8*2=16  8*3=24  8*4=32  8*5=40  8*6=48  8*7=56  8*8=64  8*9=72  
9*1=9   9*2=18  9*3=27  9*4=36  9*5=45  9*6=54  9*7=63  9*8=72  9*9=81  
********************************************************************************
1*1=1   
2*1=2   2*2=4   
3*1=3   3*2=6   3*3=9   
4*1=4   4*2=8   4*3=12  4*4=16  
5*1=5   5*2=10  5*3=15  5*4=20  5*5=25  
6*1=6   6*2=12  6*3=18  6*4=24  6*5=30  6*6=36  
7*1=7   7*2=14  7*3=21  7*4=28  7*5=35  7*6=42  7*7=49  
8*1=8   8*2=16  8*3=24  8*4=32  8*5=40  8*6=48  8*7=56  8*8=64  
9*1=9   9*2=18  9*3=27  9*4=36  9*5=45  9*6=54  9*7=63  9*8=72  9*9=81  
********************************************************************************
1*1=1   1*2=2   1*3=3   1*4=4   1*5=5   1*6=6   1*7=7   1*8=8   1*9=9   
        2*2=4   2*3=6   2*4=8   2*5=10  2*6=12  2*7=14  2*8=16  2*9=18  
                3*3=9   3*4=12  3*5=15  3*6=18  3*7=21  3*8=24  3*9=27  
                        4*4=16  4*5=20  4*6=24  4*7=28  4*8=32  4*9=36  
                                5*5=25  5*6=30  5*7=35  5*8=40  5*9=45  
                                        6*6=36  6*7=42  6*8=48  6*9=54  
                                                7*7=49  7*8=56  7*9=63  
                                                        8*8=64  8*9=72  
                                                                9*9=81  



例3.16 显示100~200之间不能被3整除的数


程序如下:

'''
1. 例3.16:显示100~200之间不能被3整除的数-P54
   (1) 第3章-程序流程控制
       3.3 循环语句
           3.3.7 continue语句

2. 2021年5月2日 星期日
'''

j = 0  # 控制一行显示数值的个数
print('100~200之间不能被3整除的数为:')
for i in range(100,200+1):
    if (i % 3 == 0): continue # 跳过被3整除的数
    # 每个数占5个位置,不足后面加空格,并且不换行
    print(str.format("{0:<5}",i),end="")
    j += 1
    # 每行显示10个数后换行
    if (j % 10 == 0): print()


运行结果如下:

100~200之间不能被3整除的数为:
100  101  103  104  106  107  109  110  112  113  
115  116  118  119  121  122  124  125  127  128  
130  131  133  134  136  137  139  140  142  143  
145  146  148  149  151  152  154  155  157  158  
160  161  163  164  166  167  169  170  172  173  
175  176  178  179  181  182  184  185  187  188  
190  191  193  194  196  197  199  200  



第4章 常用内置数据类型




第5章 系列数据类型



5.3 元组



5.3.2 tuple对象创建元组实例对象


  • tuple()

    创建空的元组

  • tuple(iterable)

    创建空的元组,包括可枚举对象iterable中的元素



例5.10 使用tuple创建元组实例对象

t1 = tuple() # 创建空的元组
t2 = tuple('abc')
t3 = tuple([1,2,3])
t4 = tuple(range(3))
print(t1,t2,t3,t4)


运行结果

() ('a', 'b', 'c') (1, 2, 3) (0, 1, 2)



第8章 函数



8.3.5 可选参数

  • 声明函数时,

    可选参数需要指定默认值

  • 调用函数是,

    若可选参数未传入对应实参值,则可选参数使用定义时的默认值


  • 函数声明参数时,需要先声明没有默认值的参数,再声明具有默认值的参数。



例8.15 可选参数

  • 代码示例
def my_sum1(mid_score,end_score,mid_rate=0.4):
    score = mid_score*mid_rate + end_score*(1 - mid_rate)
    print(format(score,'.2f'))
my_sum1(88,79)
  • 运行结果
82.60



8.3.6 位置参数和命名参数

  • 函数调用时,实参默认按照位置顺序传递给形参。

    按位置传递的参数称为位置参数

  • 函数调用时,亦可以按照指定名称传入参数,

    按指定名称传入的参数称为命名参数,也称为关键字参数

    • 命名参数的优点:①参数名称意义明确,②传递的参数与顺序无关;③如果有多个可选参数,则可选择指定某个参数值。



例8.16


  • 代码示例
def my_sum2(mid_score,end_score,mid_rate=0.4):
    
    # 基于期中成绩、期末成绩和权重计算总评成绩
    score = mid_score * mid_rate + end_score*(1-mid_rate)
    print(format(score,'.2f')) # 输出总评成绩,保留两位小数

my_sum2(88,79)  # 按位置传递
my_sum2(mid_score=88,end_score=79) # 按名称传递
my_sum2(end_score=79,mid_score=88) # 按名称传递

  • 运行结果
82.60
82.60
82.60



8.3.7 可变参数

  • 声明函数时,带星号的参数,表示可以向函数传递可变数量的实参,

    调用函数时,从该点后,所有参数被收集为一个元组



    +声明函数时,带双星号的参数,表示可以向该参数传递可变数量的实参。

    调用函数时,从哪一点以后的所有参数被收集为一个字典


  • 带星号或者双星号的参数必须位于形参列表的最后位置



例8.17 可变参数示例1


  • 代码示例:
# 例8.17 可变参数示例
def my_sum3(a,b,*c):  # 各数字累加和
    total = a + b
    for n in c:
        total = total + n
    return total

print(my_sum3(1,2))
print(my_sum3(1,2,3,4))
print(my_sum3(1,2,3,4,5,6,7))

  • 运行结果:
3
10
28



例8.18 可变参数示例2


  • 代码示例
# 例8.18 利用带星号和带双星号的参数计算各数字累加和
def my_sum4(a,b,*c,**d):
    total = a + b
    for n in c:
        total = total + n
    for key in d:
        total = total + d[key]
    
    return total

print(my_sum4(1,2))
print(my_sum4(1,2,3,4,5))
print(my_sum4(1,2,3,4,5,male=6,female=7))

  • 运行结果
3
15
28



8.3.8 强制命名参数

  • 在带星号的参数后面申明参数会导致

    强制命名参数,调用时需要显示的使用名称传递

    。因为按照位置传递的参数默认收集为一个元组,传递给前面带星号的可变参数。
  • 如果不需要带星号的可变参数,只想使用强制命名参数,

    可以简单的使用一个星号



例8.19 强制命名参数示例


  • 代码示例
# 例8.19 强制命名参数使用示例
def my_sum(*,mid_score,end_score,mid_rate=0.4):
    score = mid_score*mid_rate + end_score*(1-mid_rate)
    print(format(score,'.2f')) # 输出吧总成绩,保留两位小数
my_sum(mid_score=88,end_score=90)
my_sum(end_score=90,mid_score=88)
my_sum(88,90) # 报错,必须显示的使用命名参数传递

  • 运行结果
89.20
89.20
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-980eb3f5fc34> in <module>
      5 my_sum(mid_score=88,end_score=90)
      6 my_sum(end_score=90,mid_score=88)
----> 7 my_sum(88,90) # 报错,必须显示的使用命名参数传递

TypeError: my_sum() takes 0 positional arguments but 2 were given




第9章 类和函数

  • 类是一种数据结构,可以包含数据成员和函数成员。



9.1 面向对象概念

面向对象的程序设计具有三个基本特征:封装、继承和多态,可以大大增加程序的可靠性、代码的可重用性和程序的可维护性。



9.2 类对象和实例对象



9.2.1 类对象

类使用关键字class声明。类的声明格式如下:

class 类名
	类体
  • 类名的命名规则:一般由多个单词组成,除第1个字母大写之外,其余字母均小写
  • 定义在类体内的元素都是类的成员。类的主要成员包括两种类型,即描述状态的数据成员(属性)和描述操作的函数成员(方法)。



9.2.2 实例对象


类是抽象的,要使用类定义的功能,就必须将类实例化,即创建类的对象。创建对象之后可以使用“.”运算符来调用其成员。



9.3 属性

类的数据成员是在类中定义的成员变量(域),用来存储描述类的特征值,称为属性。



9.3.1 实例属性

  • 通过“self.变量名”定义的属性称为实例属性,也称为实例变量。
  • 类的每个实例都包含该类的实例变量的一个单独副本,实例变量属于单独的实例。
  • 实例变量在类的内部通过self访问,在外部通过对象实例访问
  • 实例属性一般在__init__方法中通过如下形式进行初始化:
self.实例变量名 = 初始值



例9.3 实例属性示例


  • 代码:
'''
1. 例9.3:实例属性示例

2. 2021年6月7日
'''
class Person2:  # 定义Person2类
    def __init__(self,name,age):  # __init__方法
        self.name = name # 初始化self.name,即成员变量name
        self.age = age  # 初始化self.age,即成员变量age
    def say_hi(self):   # 定义类Person2的函数sayHi
        print('您好,我叫',self.name) # 在实例方法中通过self.name读取成员变量
                                      # name(域)

p1 = Person2('张三',25) # 创建对象
p1.say_hi() # 调用对象的方法
print(p1.age) # 通过p1.age(obj1.变量名)读取成员变量age(域)

  • 运行结果:
您好,我叫 张三
25



9.3.2 类属性

  • Python允许声明属于类对象本身的变量,即类属性,也称为类变量、静态属性。
  • 类属性属于整个类,不是特定实例的一部分,是所有实例之间共享的一个副本。



9.3.3 私有属性和公有属性

  • Python中约定两个下划线开头,但是不以两个下划线结束的属性是私有的(private),其他为公共的(public)。
  • 不能直接方位私有属性,但可以在方法中访问。



例9.5 私有属性示例


  • 代码示例:
class A:
    __name = 'class A' #私有属性
    def get_name():
        print(A.__name) # 在类方法中访问私有属性

A.get_name()
A.__name() # 导致错误,不能直接访问私有类属性

+

运行结果:

class A
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-29d60170158b> in <module>
      5 
      6 A.get_name()
----> 7 A.__name() # 导致错误,不能直接访问私有类属性

AttributeError: type object 'A' has no attribute '__name'



9.4 方法



9.4.1 实例方法

  • 方法是与类相关的函数,类方法的定义与普通的函数一致。
  • 一般情况下,类方法的第一个参数一般为self,这种方法称为实例方法。
  • 实例方法对类的某个给定的实例进行操作,可以通过self显式地访问该实例。
  • 实例方法的声明格式如下:
def 方法名(self,[形参列表]):
	函数体
  • 方法的调用格式如下:
对象.方法名([实参列表])
  • 需要注意的是,类方法的第一个参数为self,但调用时,用户不需要也不能给该参数传值。

    事实上,Python自动把对象实例传递给参数。



例9.10


  • 代码示例:
class Person4:
    def say_hi(self,name):
        self.name = name
        print('您好,我叫',self.name)

p4 = Person4()
p4.say_hi('Alice')

  • 运行结果:
您好,我叫 Alice



9.4.2 静态方法

  • 静态方法通过装饰器@staticmethod来定义,其声明格式如下:
@staticmethod
def 静态方法名([形参列表]):
	函数体

其调用格式如下:

类名.静态方法名([实参列表])



例 9.11


  • 代码:
class TemperatureConverter:
    @staticmethod
    def c2f(t_c): # 摄氏温度到华氏温度的转换
        t_c = float(t_c)
        t_f = (t_c * 9/5) + 32
        return t_f
    @staticmethod
    def f2c(t_f): # 华氏温度到摄氏温度的转换
        t_f = float(t_f)
        t_c = (t_f - 32) * 5/9
        return t_c
    
# 测试代码
print("1. 从摄氏温度到华氏温度.")
print("2. 从华氏温度到摄氏温度.")
choice = int(input("请选择转换方向:"))
if choice == 1:
    t_c = float(input("请输入摄氏温度:"))
    t_f = TemperatureConverter.c2f(t_c)
    print("华氏温度为:{0:.2f}".format(t_f))
elif choice == 2:
    t_f = float(input("请输入华氏温度:"))
    t_c = TemperatureConverter.f2c(t_f)
    print("华氏温度为:{0:.2f}".format(t_f))
    print("摄氏温度为:{0:.2f}".format(t_c))
else:
    print("无此选项,只能选择1或2!")

  • 运行结果:
1. 从摄氏温度到华氏温度.
2. 从华氏温度到摄氏温度.
请选择转换方向:2
请输入华氏温度:22
华氏温度为:22.00
摄氏温度为:-5.56



9.4.3 类方法

  • Python允许声明属于类本身的方法,即类方法。
  • 类方法不对特定实例进行操作,在类方法中访问对象实例属性会导致错误。
  • 类方法通过装饰器@classmethod来定义,第一个形式参数必须为类对象本身,通常为cls。类方法的声明格式如下:
@classmethod
def 类方法名(cls, [形参列表]):
	函数体
  • 类方法一般通过类名来访问,也可以通过对象实例来调用。其调用格式如下:
类名.类方法名([实参列表])