【天池龙珠计划寒假训练营】python学习笔记(一):从变量到异常处理

一、变量、运算符与数据类型

1.1注释

在 Python 中,# 表示注释,作用于整行。
''' '''或者""" """表示区间注释,在三引号之间的所有内容被注释

例1.1.1

# 写下你的答案
print("hello world")

1.2运算符

- 算数运算符

操作符 名称 示例
+ 1+1
- 2-1
* 3*4
/ 除以 3/4
// 整除(地板除) 3//4
% 取余 3%4
** 2**3

- 比较运算符

操作符 名称 示例
> 大于 2 > 1
>= 大于等于 2 >= 4
< 小于 1 < 2
<= 小于等于 5 <= 2
== 等于 3 == 4
!= 不等于 3 != 5

- 逻辑运算符

操作符 名称 示例
and (3 > 2) and (3 < 5)
or (1 > 3) or (9 < 2)
not not (2 > 1)

- 位运算符

操作符 名称 示例
~ 按位取反 ~4
& 按位与 4 & 5
| 按位或 4|5
^ 按位异或 4 ^ 5
<< 左移 4 << 2
>> 右移 4 >> 2

例1.2.1

print(bin(4))  # 0b100
print(bin(5))  # 0b101
print(bin(~4), ~4)  # -0b101 -5
print(bin(4 & 5), 4 & 5)  # 0b100 4
print(bin(4 | 5), 4 | 5)  # 0b101 5
print(bin(4 ^ 5), 4 ^ 5)  # 0b1 1
print(bin(4 << 2), 4 << 2)  # 0b10000 16
print(bin(4 >> 2), 4 >> 2)  # 0b1 1

在这里插入图片描述
问题1:按位取反?为什么~4=-5呢?

  • 二进制数
    按位取反是位运算符,而位运算符是应用在两个数的运算上,会对数字的二进制所有位数进行从低到高的运算。所以需要把十进制数转换成二进制数再进行运算。
  • 补码
    补码是属于计算机三种机械数的一种,机械数有原码、反码、补码。
    如果是正数,那么原码 = 反码 = 补码,正数的符号位为0(如 0 100,这里的0就是符号位,负数类似);
    如果是负数,那么反码就是把原码的每一位取反,也就是0变成1,1变成0;补码就是在反码的基础上,末位+1,负数的符号位为1。
  • 计算~4=-5
    第一步,把十进制数4转化成二进制数100;
    第二步,由于二进制数在内存中以补码的形式存储,所以将得到的二进制数转成补码,要成补码先要把原码转成反码(即0 100,正数原反补一样,第一个0就是符号位),然后反码得到补码(即0 100,正数原反补一样);
    第三步,终于进行按位取反啦!把第二步得到的补码进行按位取反(即1 011);
    第四步,把第三步的操作转为补码(因为敲重点:二进制数在内存中以补码的形式存储!!!,所以就需要把取反后的二进制数,转成补码),但是由于按位取反后变为负数,所以我们需要应用负数的原反补规则,先变成反码(即1 011),然后反码末位+1得到补码(即1 101);
    第五步,把得到的补码101转成十进制数就是5,然后符号位是1,故~4结果为-5)。
  • 快捷公式:~x = -(x+1)

(解决方法参考链接:https://www.cnblogs.com/jniantic/p/12189648.html)

问题2:位运算解释(详细示例转到“二、位运算”)

  • &:按位与运算符,参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0。
  • |:按位或运算符,只要对应的二个二进位有一个为1时,结果位就为1。
  • ^:按位异或运算符,当两对应的二进位相异时,结果为1。
  • ~:按位取反运算符,对数据的每个二进制位取反,即把1变为0,把0变为1 。
  • <<:左移动运算符,运算数的各二进位全部左移若干位,由<< 右边的数字指定了移动的位数,高位丢弃,低位补0。
  • >>:右移动运算符,把运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数。

注:bin()函数
bin()函数用于将数字转换为二进制。如果将数字传递给该bin()函数,则它将返回该数字的二进制表示形式。
Python中的二进制数字以0b开头。该bin()函数的结果也以0b开头。

- 三元运算符
学会三元操作符的条件表达式,可以使用一条语句来完成以上的条件判断和赋值操作。

例1.2.2

x, y = 4, 5
if x < y:
    small = x
else:
    small = y

print(small)  # 4
x, y = 4, 5
small = x if x < y else y
print(small)  # 4

-其他运算符

操作符 名称 示例
in 存在 ‘A’ in [‘A’, ‘B’, ‘C’]
not in 不存在 ‘h’ not in [‘A’, ‘B’, ‘C’]
is “hello” is “hello”
not is 不是 “hello” is not “hello”

例1.2.3

打印判断:

letters = ['A', 'B', 'C']
if 'A' in letters:
    print('A' + ' exists')
if 'h' not in letters:
    print('h' + ' not exists')

# A exists
# h not exists

比较两个变量均指向不可变类型:

a = "hello"
b = "hello"
print(a is b, a == b)  # True True
print(a is not b, a != b)  # False False

比较的两个变量均指向可变类型:

a = ["hello"]
b = ["hello"]
print(a is b, a == b)  # False True
print(a is not b, a != b)  # True False

在这里插入图片描述
注意:

  • is, is not 对比的是两个变量的内存地址
  • ==, != 对比的是两个变量的值
  • 比较的两个变量,指向的都是地址不可变的类型(str等),那么is,is not 和 ==,!= 是完全等价的。
  • 对比的两个变量,指向的是地址可变的类型(list,dict,tuple等),则两者是有区别的。

-运算符的优先级

操作符 描述
** 指数(最高优先级)
按位翻转,一元加号和减号
* / % // 乘,除,取模和取整除)
+ - 加法减法
>> << 右移,左移运算符
& 位‘AND’
^| 位运算符
<=<>>= 比较运算符
<>==!= 等于运算符
=%=/=//=-=+==*= 赋值运算符
is is not 身份运算符
in not in 成员运算符
not and or 逻辑运算符

例1.2.4

print(-3 ** 2)  #= (-3)^2=-9
print(3 ** -2)  #=3^(-2)=0.1111111111111111
print(1 << 3 + 2 & 7)  # 0
print(-3 * 2 + 5 / -2 - 4)  # -12.5
print(3 < 4 and 4 < 5)  # True

1.3变量和赋值

  1. 在使用变量之前,需要对其先赋值。
  2. 变量名可以包括字母、数字、下划线、但变量名不能以数字开头。
  3. Python 变量名是大小写敏感的,foo != Foo。

例1.3.1

x = "小白的程序人生"
print(x) # 小白的程序人生
x = "大白的程序人生"
print(x) # 大白的程序人生
first = 2
second = 3
third = first + second
print(third) # 5
x1 = "大白的程序人生"
x2 = "小白的程序人生"
x3 = x1 + x2
print(x3) # 大白的程序人生小白的程序人生

1.4数据类型与转换

类型 名称 示例
int 整型 -876, 10
float 浮点型 3.149, 11.11
bool 布尔型 True, False

- 整型

Python 里面万物皆对象(object),整型也不例外,只要是对象,就有相应的属性 (attributes) 和方法(methods)。

例1.4.1
找到一个整数的二进制表示,再返回其长度。

a = 1031
print(bin(a)) # 0b10000000111
print(a.bit_length()) # 11

- 浮点型

print(1, type(1))
# 1 
print(1., type(1.))
# 1.0 
a = 0.00000023
b = 2.3e-7
print(a) # 2.3e-07
print(b) # 2.3e-07

有时候我们想保留浮点型的小数点后 n 位。可以用 decimal 包里的 Decimal 对象和 getcontext() 方法来实现。

import decimal
from decimal import Decimal

Python 里面有很多用途广泛的包 (package),用什么你就引进 (import) 什么。包也是对象,也可以用上面提到
dir(decimal) 来看其属性和方法。比如 getcontext() 显示了 Decimal 对象的默认精度值是 28 位 ( prec=28 ),
展示如下:

a = decimal.getcontext()
print(a)
# Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=
[], traps=[InvalidOperation, DivisionByZero, Overflow])

那保留 4 位呢?用 getcontext().prec 来调整精度。

decimal.getcontext().prec = 4
c = Decimal(1) / Decimal(3)
print(c)
# 0.3333

- 布尔型
布尔 (boolean) 型变量只能取两个值, TrueFalse 。当把布尔变量用在数字运算中,用 1 和 0 代表 TrueFalse

print(True + True) # 2
print(True + False) # 1
print(True * False) # 0

除了直接给变量赋值 TrueFalse ,还可以用 bool(X) 来创建变量,其中 X 可以是

  1. 基本类型:整型、浮点型、布尔型
  2. 容器类型:字符、元组、列表、字典和集

bool 作用在基本类型变量: X 只要不是整型 0 、浮点型 0.0bool(X) 就是 True ,其余就是 False
bool 作用在容器类型变量: X 只要不是空的变量, bool(X) 就是 True ,其余就是 False
确定 bool(X) 的值是 True 还是 False ,就看 X 是不是空,空的话就是 False ,不空的话就是 True

  1. 对于数值变量, 0 , 0.0 都可认为是空的。
  2. 对于容器变量,里面没元素就是空的。

- 获取类型信息

  1. 获取类型信息 type(object)
print(type(1)) # 
print(type(5.2)) # 
print(type(True)) # 
print(type('5.2')) # 

2.获取类型信息 isinstance(object, classinfo)

print(isinstance(1, int)) # True
print(isinstance(5.2, float)) # True
print(isinstance(True, bool)) # True
print(isinstance('5.2', str)) # True

注:

  1. type() 不会认为子类是一种父类类型,不考虑继承关系。
  2. isinstance() 会认为子类是一种父类类型,考虑继承关系。 如果要判断两个类型是否相同推荐使用 isinstance()

如果要判断两个类型是否相同推荐使用 isinstance()

- 类型转换

  1. 转换为整型 int(x, base=10)
  2. 转换为字符串 str(object='')
  3. 转换为浮点型 float(x)
    例1.4.2
print(int('520')) # 520
print(int(520.52)) # 520
print(float('520.52')) # 520.52
print(float(520)) # 520.0
print(str(10 + 10)) # 20
print(str(10.1 + 5.2)) # 15.3

1.5 print()函数

1 print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
  1. 将对象以字符串表示的方式格式化输出到流文件对象file里。其中所有非关键字参数都按 str() 方式进行转换为字符
    串输出;
  2. 关键字参数 sep 是实现分隔符,比如多个参数输出时想要输出中间的分隔字符;
  3. 关键字参数 end 是输出结束时的字符,默认是换行符 \n
  4. 关键字参数 file 是定义流输出的文件,可以是标准的系统输出 sys.stdout ,也可以重定义为别的文件;
  5. 关键字参数 flush 是立即把内容输出到流文件,不作缓存。

例1.5.1
没有参数时,每次输出后都会换行。

shoplist = ['apple', 'mango', 'carrot', 'banana']
print("This is printed without 'end'and 'sep'.")
for item in shoplist:
print(item)
# This is printed without 'end'and 'sep'.
# apple
# mango
# carrot
# banana

每次输出结束都用 end 设置的参数 & 结尾,并没有默认换行。

shoplist = ['apple', 'mango', 'carrot', 'banana']
print("This is printed with 'end='&''.")
for item in shoplist:
 print(item, end='&')
print('hello world')
# This is printed with 'end='&''.
# apple&mango&carrot&banana&hello world

item 值与 'another string' 两个值之间用 sep 设置的参数 & 分割。由于 end 参数没有设置,因此默认是输出解释后换行,即 end 参数的默认值为 \n 。

shoplist = ['apple', 'mango', 'carrot', 'banana']
print("This is printed with 'sep='&''.")
for item in shoplist:
print(item, 'another string', sep='&')
# This is printed with 'sep='&''.
# apple&another string
# mango&another string
# carrot&another string
# banana&another string

二、位运算

2.1 原码、反码和补码

二进制有三种不同的表示形式:原码、反码和补码,计算机内部使用补码来表示。

  • 原码:就是其二进制表示(注意,有一位符号位)。
  • 反码:正数的反码就是原码,负数的反码是符号位不变,其余位取反(对应正数按位取反)。
  • 补码:正数的补码就是原码,负数的补码是反码+1。
  • 符号位:最高位为符号位,0表示正数,1表示负数。在位运算中符号位也参与运算。

2.2 按位非操作~

~ 1 = 0
~ 0 = 1

~ 把 num 的补码中的 0 和 1 全部取反(0 变为 1,1 变为 0)有符号整数的符号位在 ~ 运算中同样会取反。

00 00 01 01 -> 5
~
---
11 11 10 10 -> -6
11 11 10 11 -> -5
~
---
00 00 01 00 -> 4

2.3 按位与操作&

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0

只有两个对应位都为 1 时才为 1

00 00 01 01 -> 5
&
00 00 01 10 -> 6
---
00 00 01 00 -> 4

2.4 按位或操作|

1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0

只要两个对应位中有一个 1 时就为 1

00 00 01 01 -> 5
|
00 00 01 10 -> 6
---
00 00 01 11 -> 7

2.5 按位异或操作^

1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

只有两个对应位不同时才为 1

00 00 01 01 -> 5
^
00 00 01 10 -> 6
---
00 00 00 11 -> 3

异或操作的性质:满足交换律和结合律

A: 00 00 11 00
B: 00 00 01 11
A^B: 00 00 10 11
B^A: 00 00 10 11
A^A: 00 00 00 00
A^0: 00 00 11 00
A^B^A: = A^A^B = B = 00 00 01 11

2.6 按位左移操作<<

num << inum 的二进制表示向左移动 i 位所得的值。

00 00 10 11 -> 11
11 << 3
---
01 01 10 00 -> 88

2.7 按位右移操作>>

num >> inum 的二进制表示向右移动 i 位所得的值。

00 00 10 11 -> 11
11 >> 2
---
00 00 00 10 -> 2

2.8 利用位运算实现快速计算

通过 <<>> 快速计算2的倍数问题。

n << 1 -> 计算 n*2
n >> 1 -> 计算 n/2,负奇数的运算不可用
n << m -> 计算 n*(2^m),即乘以 2 的 m 次方
n >> m -> 计算 n/(2^m),即除以 2 的 m 次方
1 << n -> 2^n

通过 ^ 快速交换两个整数。

a ^= b
b ^= a
a ^= b

通过 a & (-a) 快速获取 a 的最后为 1 位置的整数。

00 00 01 01 -> 5
&
11 11 10 11 -> -5
---
00 00 00 01 -> 1
00 00 11 10 -> 14
&
11 11 00 10 -> -14
---
00 00 00 10 -> 2

2.9利用位运算实现整数集合

一个数的二进制表示可以看作是一个集合(0 表示不在集合中,1 表示在集合中)。
比如集合 {1, 3, 4, 8} ,可以表示成 01 00 01 10 10 而对应的位运算也就可以看作是对集合进行的操作。

  • 元素与集合的操作:
a | (1<<i) -> 把 i 插入到集合中
a & ~(1<<i) -> 把 i 从集合中删除
a & (1<<i) -> 判断 i 是否属于该集合(零不属于,非零属于)
  • 集合之间的操作:
a 补 -> ~a
a 交 b -> a & b
a 并 b -> a | b
a 差 b -> a & (~b)

整数在内存中是以补码的形式存在的,输出自然也是按照补码输出。

class Program
{
     
static void Main(string[] args)
 {
     
 string s1 = Convert.ToString(-3, 2);
 Console.WriteLine(s1);
// 11111111111111111111111111111101
 string s2 = Convert.ToString(-3, 16);
 Console.WriteLine(s2);
// fffffffd
 }
}

但我们看一下 Python 的 bin() 输出。

print(bin(3)) # 0b11
print(bin(-3)) # -0b11
print(bin(-3 & 0xffffffff))
# 0b11111111111111111111111111111101
print(bin(0xfffffffd))
# 0b11111111111111111111111111111101
print(0xfffffffd) # 4294967293

是不是很颠覆认知,我们从结果可以看出:

  • Python中 bin 一个负数(十进制表示),输出的是它的原码的二进制表示加上个负号,巨坑。
  • Python中的整型是补码形式存储的。
  • Python中整型是不限制长度的不会超范围溢出。
    所以为了获得负数(十进制表示)的补码,需要手动将其和十六进制数 0xffffffff 进行按位与操作,再交给 bin() 进行输出,得到的才是负数的补码表示。

在这里插入图片描述
思考题: 只出现一次的数字:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。尝试使用位运算解决此题。
题目说明:

file result1: 1 result2: 4 """ class Solution: def singleNumber(self,
nums: List[int]) -> int:
# your code here ```

解法: 异或
异或运算的特点:两个相同的数字异或,结果为0。 因为数组中除了一个元素只出现一次之外,其它的元素都出现两次,如果把所有的数都异或,相同的数字异或为0,最后只剩下出现一次的数字,它和0异或,结果就是它本身。

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。  * 找出那个只出现了一次的元素。  */   class
Solution {
      
    public int singleNumber(int[] nums) {
      
        int num = 0;
        for(int i = 0; i < nums.length; i++){
      
            num = num ^ nums[i];
        }
        return num;
    } }
    public class Test {
      
    public static void main(String[] args) {
      
        int[] data = new int[]{
      17,12,5,-6,12,4,17,-5,2,-3,2,4,5,16,-3,-4,15,15,-4,-5,-6};
        Solution sol = new Solution();
        System.out.println(sol.singleNumber(data));
    } } ``

(解决方法参考链接:https://blog.csdn.net/baidu_40931662/article/details/83892506)

三、条件语句

3.1 if语句

if expression:
 expr_true_suite
  1. if 语句的 expr_true_suite 代码块只有当条件表达式 expression 结果为真时才执行,否则将继续执行紧跟在该
    代码块后面的语句。
  2. 单个 if 语句中的 expression 条件表达式可以通过布尔操作符 andornot 实现多重条件判断。
if 2 > 1 and not 2 > 3:
 print('Correct Judgement!')
# Correct Judgement!

3.2 if-else语句

if expression:
 expr_true_suite
else
 expr_false_suite
  1. Python 提供与 if 搭配使用的 else,如果 if 语句的条件表达式结果布尔值为假,那么程序将执行 else 语句后的代码。
  2. if 语句支持嵌套,即在一个 if 语句中嵌入另一个 if 语句,从而构成不同层次的选择结构。Python 使用缩进而不是大括号来标记代码块边界,因此要特别注意 else 的悬挂问题。
temp = input("不妨猜一下小哥哥现在心里想的是那个数字:")
guess = int(temp)
if guess > 8:
 print("大了,大了")
else:
if guess == 8:
print("你这么懂小哥哥的心思吗?")
print("哼,猜对也没有奖励!")
else:
 print("小了,小了")
print("游戏结束,不玩儿啦!")

3.3 if-elif-else语句

  1. elif 语句即为 else if,用来检查多个表达式是否为真,并在为真时执行特定代码块中的代码。
temp = input('请输入成绩:')
source = int(temp)
if 100 >= source >= 90:
    print('A')
elif 90 > source >= 80:
    print('B')
elif 80 > source >= 60:
    print('C')
elif 60 > source >= 0:
    print('D')
else:
    print('输入错误!')

3.4 assert关键词

  1. assert 这个关键词我们称之为“断言”,当这个关键词后边的条件为 False 时,程序自动崩溃并抛
    AssertionError 的异常。
my_list = ['lsgogroup']
my_list.pop(0)
assert len(my_list) > 0
# AssertionError
  1. 在进行单元测试时,可以用来在程序中置入检查点,只有条件为 True 才能让程序正常工作。
assert 3 > 7
# AssertionError

四、循环语句

4.1 while 循环

while 语句最基本的形式包括一个位于顶部的布尔表达式,一个或多个属于 while 代码块的缩进语句。
while 循环的代码块会一直循环执行,直到布尔表达式的值为布尔假。
如果布尔表达式不带有 <、>、==、!=、in、not in 等运算符,仅仅给出数值之类的条件,也是可以的。当 while 后写
入一个非零整数时,视为真值,执行循环体;写入 0 时,视为假值,不执行循环体。也可以写入 str、list 或任何序
列,长度非零则视为真值,执行循环体;否则视为假值,不执行循环体。

count = 0
while count < 3:
    temp = input("不妨猜一下小哥哥现在心里想的是那个数字:")
    guess = int(temp)
    if guess > 8:
        print("大了,大了")
    else:
        if guess == 8:
            print("你是小哥哥心里的蛔虫吗?")
            print("哼,猜对也没有奖励!")
            count = 3
        else:
            print("小了,小了")
    count = count + 1
print("游戏结束,不玩儿啦!")

布尔表达式返回0,循环终止。

string = 'abcd'
while string:
    print(string)
    string = string[1:]
# abcd
# bcd
# cd
# d

4.2 while - else 循环

while 循环正常执行完的情况下,执行 else 输出,如果 while 循环中执行了跳出循环的语句,比如 break ,将不执行 else 代码块的内容。

count = 0
while count < 5:
    print("%d is less than 5" % count)
    count = count + 1
else:
     print("%d is not less than 5" % count)
# 0 is less than 5
# 1 is less than 5
# 2 is less than 5
# 3 is less than 5
# 4 is less than 5
# 5 is not less than 5
count = 0
while count < 5:
    print("%d is less than 5" % count)
    count = 6
    break
else:
    print("%d is not less than 5" % count)

4.3 for 循环

for 循环是迭代循环,在Python中相当于一个通用的序列迭代器,可以遍历任何有序序列,如 str、list、tuple 等,也可以遍历任何可迭代对象,如 dict
每次循环,迭代变量被设置为可迭代对象的当前元素,提供给代码块使用。

member = ['张三', '李四', '刘德华', '刘六', '周润发']
for each in member:
    print(each)
# 张三
# 李四
# 刘德华
# 刘六
# 周润发
for i in range(len(member)):
    print(member[i])
# 张三
# 李四
# 刘德华
# 刘六
# 周润发


dic = {
     'a': 1, 'b': 2, 'c': 3, 'd': 4}
for value in dic.values():
    print(value, end=' ')
# 1 2 3 4

4.4 for - else 循环

for 循环正常执行完的情况下,执行 else 输出,如果 for 循环中执行了跳出循环的语句,比如 break ,将不执行 else 代码块的内容,与 while - else 语句一样。

for num in range(10, 20): # 迭代 10 到 20 之间的数字
    for i in range(2, num): # 根据因子迭代
        if num % i == 0: # 确定第一个因子
            j = num / i # 计算第二个因子
            print('%d 等于 %d * %d' % (num, i, j))
            break # 跳出当前循环
    else: # 循环的 else 部分
        print(num, '是一个质数')
# 10 等于 2 * 5
# 11 是一个质数
# 12 等于 2 * 6
# 13 是一个质数
# 14 等于 2 * 7
# 15 等于 3 * 5
# 16 等于 2 * 8
# 17 是一个质数
# 18 等于 2 * 9
# 19 是一个质数

4.5 range() 函数

range([start,] stop[, step=1])
  1. 这个BIF(Built-in functions)有三个参数,其中用中括号括起来的两个表示这两个参数是可选的。
  2. step=1 表示第三个参数的默认值是1。
  3. range 这个BIF的作用是生成一个从 start 参数的值开始到 stop 参数的值结束的数字序列,该序列包含 start
    值但不包含 stop 的值。
for i in range(2, 9): # 不包含9
    print(i)
# 2
# 3
# 4
# 5
# 6
# 7
# 8

for i in range(1, 10, 2):
    print(i)
# 1
# 3
# 5
# 7
# 9

4.6 enumerate()函数

enumerate(sequence, [start=0])
  1. sequence – 一个序列、迭代器或其他支持迭代对象。
  2. start – 下标起始位置。
  3. 返回 enumerate(枚举) 对象
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
lst = list(enumerate(seasons))
print(lst)
# [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
lst = list(enumerate(seasons, start=1)) # 下标从 1 开始
print(lst)
# [(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

enumerate()for 循环的结合使用

for i, a in enumerate(A)
 do something with a 

enumerate(A) 不仅返回了 A 中的元素,还顺便给该元素一个索引值 (默认从 0 开始)。此外,用enumerate(A, j) 还可以确定索引起始值为 j

languages = ['Python', 'R', 'Matlab', 'C++']
for language in languages:
    print('I love', language)
    print('Done!')
'''
I love Python
I love R
I love Matlab
I love C++
Done!
'''
for i, language in enumerate(languages, 2):
    print(i, 'I love', language)
    print('Done!')
'''
2 I love Python
3 I love R
4 I love Matlab
5 I love C++
Done!
'''

4.7 break 语句

break 语句可以跳出当前所在层的循环。
具体示例参考之前的循环案例。

4.8 continue 语句

continue 终止本轮循环并开始下一轮循环。

for i in range(10):
    if i % 2 != 0:
        print(i)
        continue
    i += 2
    print(i)
# 2
# 1
# 4
# 3
# 6
# 5
# 8
# 7
# 10
# 9

4.9 pass 语句

pass 语句的意思是“不做任何事”,如果你在需要有语句的地方不写任何语句,那么解释器会提示出错,而 pass 语句就是用来解决这些问题的。

def a_func():
# SyntaxError: unexpected EOF while parsing
def a_func():
    pass

注:
pass 是空语句,不做任何操作,只起到占位的作用,其作用是为了保持程序结构的完整性。尽管 pass
语句不做任何操作,但如果暂时不确定要在一个位置放上什么样的代码,可以先放置一个 pass 语句,让代码可以正常运行。

4.10 推导式

- 列表推导式

[ expr for value in collection [if condition] ]

例4.10.1

x = [(i, i ** 2) for i in range(6)]
print(x)
# [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
x = [[i, j] for i in range(0, 3) for j in range(0, 3)]
print(x)
# [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
x[0][0] = 10
print(x)
# [[10, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
a = [(i, j) for i in range(0, 3) if i < 1 for j in range(0, 3) if j > 1]
print(a)
# [(0, 2)]

- 元组推导式

( expr for value in collection [if condition] )

例4.10.2

a = (x for x in range(10))
print(a)
#  at 0x0000025BE511CC48>
print(tuple(a))
# (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

- 字典推导式

{
      key_expr: value_expr for value in collection [if condition] }

例4.10.3

b = {
     i: i % 2 == 0 for i in range(10) if i % 3 == 0}
print(b)
# {0: True, 3: False, 6: True, 9: False}

- 集合推导式

{
      expr for value in collection [if condition] }

例4.10.4

c = {
     i for i in [1, 2, 3, 4, 5, 5, 6, 4, 3, 2, 1]}
print(c)
# {1, 2, 3, 4, 5, 6}

- 其他

d = 'i for i in "I Love Lsgogroup"'
print(d)
# i for i in "I Love Lsgogroup"
e = (i for i in range(10))
print(e)
#  at 0x0000007A0B8D01B0>
print(next(e)) # 0
print(next(e)) # 1
for each in e:
    print(each, end=' ')
# 2 3 4 5 6 7 8 9
s = sum([i for i in range(101)])
print(s) # 5050
s = sum((i for i in range(101)))
print(s) # 5050

4.11 综合例子

passwdList = ['123', '345', '890']
valid = False
count = 3
while count > 0:
    password = input('enter password:')
    for item in passwdList:
        if password == item:
            valid = True
            break
        
    if not valid:
        print('invalid input')
        count -= 1
        continue
    else:
        break

在这里插入图片描述
思考题1: 编写一个Python程序来查找那些可以被7除以5的整数的数字,介于1500和2700之间。
回答:

i=[num for num in range(1500,2701) if num %7==0 and num
%5==0] 
print(i)
 """
  [1505, 1540, 1575, 1610, 1645, 1680, 1715, 1750,
1785, 1820, 1855, 1890, 1925, 1960, 1995, 2030, 2065, 2100, 2135,
2170, 2205, 2240, 2275, 2310, 2345, 2380, 2415, 2450, 2485, 2520,
2555, 2590, 2625, 2660, 2695]
 """ 

在这里插入图片描述
思考题2: 龟兔赛跑游戏
题目描述:
话说这个世界上有各种各样的兔子和乌龟,但是 研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔 子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以 上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。
然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1 米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找 到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。
输入
输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2< =100;t< =300;s< =10;l< =10000且为v1,v2的公倍数)
输出
输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。
第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。
回答:

# 参数有:v1(兔子速度) v2(乌龟速度) t(兔子超出乌龟距离) s(兔子休息时间) l(赛道长度)
# v1,v2< =100;t< =300;s< =10;1< =10000且为 v1 v2公倍数 v1 =float(input('请输入兔子速度')) v2 =float(input('请输入乌龟速度')) if v1>100 or v2>100:
    print('请重输')
    v1 =float(input('请输入兔子速度'))
    v2 =float(input('请输入乌龟速度')) t =float(input('兔子超出乌龟距离')) if t>300:
    print('请重输')
    t =float(input('兔子超出乌龟距离')) s =float(input('兔子休息时间')) if t>10:
    print('请重输')
    s =float(input('兔子休息时间')) l =float(input('请输入跑道长度')) if l >10000 and l% v1!=0 and l %v2 !=0:
    print("请重新输入")
    l =float(input('请输入跑道长度')) turtle_t =l/v2 rabbit_t =(v1 -v2)*s/v1 +(l-(v1 -v2)*s/v1)/v1 word =['T','R','D'] i =0 if rabbit_t>turtle_t:
    print(word[i]) elif rabbit_t<turtle_t:
    print(word[i+1]) else:
    print(word[i+3])
"""
请输入兔子速度 
请输入乌龟速度 
兔子超出乌龟距离 
兔子休息时间请重输 
兔子休息时间 
请输入跑道长度R 
"""

参考答案:https://blog.csdn.net/hello_fengfeng/article/details/107550720

五、异常处理

异常就是运行期检测到的错误。计算机语言针对可能出现的错误定义了异常类型,某种错误引发对应的异常时,异常处理程序将被启动,从而恢复程序的正常运行。

5.1 Python 标准异常总结

  1. BaseException:所有异常的 基类
  2. Exception:常规异常的 基类
  3. StandardError:所有的内建标准异常的基类
  4. ArithmeticError:所有数值计算异常的基类
  5. FloatingPointError:浮点计算异常
  6. OverflowError:数值运算超出最大限制
  7. ZeroDivisionError:除数为零
  8. AssertionError:断言语句(assert)失败
  9. AttributeError:尝试访问未知的对象属性
  10. EOFError:没有内建输入,到达EOF标记
  11. EnvironmentError:操作系统异常的基类
  12. IOError:输入/输出操作失败
  13. OSError:操作系统产生的异常(例如打开一个不存在的文件)
  14. WindowsError:系统调用失败
  15. ImportError:导入模块失败的时候
  16. KeyboardInterrupt:用户中断执行
  17. LookupError:无效数据查询的基类
  18. IndexError:索引超出序列的范围
  19. KeyError:字典中查找一个不存在的关键字
  20. MemoryError:内存溢出(可通过删除对象释放内存)
  21. NameError:尝试访问一个不存在的变量
  22. UnboundLocalError:访问未初始化的本地变量
  23. ReferenceError:弱引用试图访问已经垃圾回收了的对象
  24. RuntimeError:一般的运行时异常
  25. NotImplementedError:尚未实现的方法
  26. SyntaxError:语法错误导致的异常
  27. IndentationError:缩进错误导致的异常
  28. TabError:Tab和空格混用
  29. SystemError:一般的解释器系统异常
  30. TypeError:不同类型间的无效操作
  31. ValueError:传入无效的参数
  32. UnicodeError:Unicode相关的异常
  33. UnicodeDecodeError:Unicode解码时的异常
  34. UnicodeEncodeError:Unicode编码错误导致的异常
  35. UnicodeTranslateError:Unicode转换错误导致的异常

异常体系内部有层次关系,Python异常体系中的部分关系如下所示:
【天池龙珠计划寒假训练营】python学习笔记(一):从变量到异常处理_第1张图片

5.2 Python标准警告总结

  1. Warning:警告的基类
  2. DeprecationWarning:关于被弃用的特征的警告
  3. FutureWarning:关于构造将来语义会有改变的警告
  4. UserWarning:用户代码生成的警告
  5. PendingDeprecationWarning:关于特性将会被废弃的警告
  6. RuntimeWarning:可疑的运行时行为(runtime behavior)的警告
  7. SyntaxWarning:可疑语法的警告
  8. ImportWarning:用于在导入模块过程中触发的警告
  9. UnicodeWarning:与Unicode相关的警告
  10. BytesWarning:与字节或字节码相关的警告
  11. ResourceWarning:与资源使用相关的警告

5.3 try - except 语句

try 语句按照如下方式工作:

  1. 首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)
  2. 如果没有异常发生,忽略 except 子句, try 子句执行后结束。
  3. 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的
    名称相符,那么对应的 except 子句将被执行。最后执行 try 语句之后的代码。
  4. 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。
try:
 f = open('test.txt')
print(f.read())
f.close()
except OSError:
print('打开文件出错')
# 打开文件出错
try:
 f = open('test.txt')
print(f.read())
f.close()
except OSError as error:
print('打开文件出错\n原因是:' + str(error))
# 打开文件出错
# 原因是:[Errno 2] No such file or directory: 'test.txt'

一个 try 语句可能包含多个 except 子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。

try:
    int("abc")
    s = 1 + '1'
    f = open('test.txt')
    print(f.read())
    f.close()
except OSError as error:
    print('打开文件出错\n原因是:' + str(error))
except TypeError as error:
    print('类型出错\n原因是:' + str(error))
except ValueError as error:
    print('数值出错\n原因是:' + str(error))
# 数值出错
# 原因是:invalid literal for int() with base 10: 'abc'
dict1 = {
     'a': 1, 'b': 2, 'v': 22}
dict1 = {
     'a': 1, 'b': 2, 'v': 22}
try:
    x = dict1['y']
except LookupError:
    print('查询错误')
except KeyError:
    print('键错误')
else:
    print(x)
# 查询错误

try-except-else 语句尝试查询不在 dict 中的键值对,从而引发了异常。这一异常准确地说应属于 KeyError ,但由
KeyErrorLookupError 的子类,且将 LookupError 置于 KeyError 之前,因此程序优先执行该 except 代码块。
所以,使用多个 except 代码块时,必须坚持对其规范排序,要从最具针对性的异常到最通用的异常。

dict1 = {
     'a': 1, 'b': 2, 'v': 22}
try:
    x = dict1['y']
except KeyError:
    print('键错误')
except LookupError:
    print('查询错误')
else:
    print(x)
# 键错误

例5.3.1
一个 except 子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组。

try:
    s = 1 + '1'
    int("abc")
    f = open('test.txt')
    print(f.read())
    f.close()
except (OSError, TypeError, ValueError) as error:
    print('出错了!\n原因是:' + str(error))
# 出错了!
# 原因是:unsupported operand type(s) for +: 'int' and 'str'

5.4 try - except - finally 语句

不管 try 子句里面有没有发生异常, finally 子句都会执行。
如果一个异常在 try 子句里被抛出,而又没有任何的 except 把它截住,那么这个异常会在 finally 子句执行后被抛出。

def divide(x, y):
    try:
        result = x / y
        print("result is", result)
    except ZeroDivisionError:
        print("division by zero!")
    finally:
        print("executing finally clause")
        
divide(2, 1)
# result is 2.0
# executing finally clause
divide(2, 0)
# division by zero!
# executing finally clause
divide("2", "1")
# executing finally clause
# TypeError: unsupported operand type(s) for /: 'str' and 'str'

5.5 try - except - else 语句

如果在 try 子句执行时没有发生异常,Python将执行 else 语句后的语句。
使用 except 而不带任何异常类型,这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息,因为它捕获所有的异常。
例5.5.1

try:
    fh = open("testfile", "w")
    fh.write("这是一个测试文件,用于测试异常!!")
except IOError:
    print("Error: 没有找到文件或读取文件失败")
else:
    print("内容写入文件成功")
    fh.close()
# 内容写入文件成功

在这里插入图片描述> 注意:
else 语句的存在必须以 except 语句的存在为前提,在没有 except 语句的 try 语句中使用
else 语句,会引发语法错误。

5.6 raise语句

Python 使用 raise 语句抛出一个指定的异常。

try:
    raise NameError('HiThere')
except NameError:
    print('An exception flew by!')
# An exception flew by!

在这里插入图片描述
思考题:猜数字游戏
题目描述: 电脑产生一个零到100之间的随机数字,然后让用户来猜,如果用户猜的数字比这个数字大,提示太大,否则提示太小,当用户正好猜中电脑会提示,“恭喜你猜到了这个数是…”。在用户每次猜测之前程序会输出用户是第几次猜测,如果用户输入的根本不是一个数字,程序会告诉用户"输入无效".
(尝试使用try catch异常处理结构对输入情况进行处理) 获取随机数采用random模块。
回答:

import random
s=random.randint(0,100)
i=1
while 1:
    print('这是第%d次猜测'%i)
    try:
        temp=input("请输入数字:")
        g=int(temp)
   except ValueError:
       print("输入无效!!!")
   else:
       if g==s:
           print('恭喜你猜到了,这个数是%d!!!'%s)
           break
       else:
           if g>s:
              print("大了!!")
           else:
              print("小了!!")
       i=i+1
print("游戏结束!!!")

答案参考:

  • 1.https://blog.csdn.net/hju22/article/details/85068852
  • 2.https://blog.csdn.net/m0_49562753/article/details/107580726

你可能感兴趣的:(python)